From 6207211ba989b502f43501a7b08f5b6c84a6c72e Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Tue, 24 Apr 2018 21:50:49 +0200
Subject: [PATCH 01/59] add skeleton for expat suport

---
 CMakeLists.txt     |  1 +
 src/CMakeLists.txt | 13 +++++++++++++
 src/exparse.c      |  7 +++++++
 src/exparse.h      |  3 +++
 src/jsonconf.c     | 15 +++++++++++++--
 5 files changed, 37 insertions(+), 2 deletions(-)
 create mode 100644 src/exparse.c
 create mode 100644 src/exparse.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 19e49c9c6..f73ba04a1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,6 +50,7 @@ else()
 find_package (SQLite3 REQUIRED QUIET)
 endif()
 
+find_package(EXPAT)
 find_package (LibXml2 REQUIRED)
 find_package (ToLua REQUIRED)
 if (TOLUA_FOUND)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index bdf0465d2..21d07e9b2 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -139,6 +139,11 @@ set (ERESSEA_SRC
   ${UTIL_SRC}
 )
 
+IF(EXPAT_FOUND)
+set (ERESSEA_SRC ${ERESSEA_SRC} exparse.c)
+ENDIF(EXPAT_FOUND)
+
+
 set(SERVER_SRC
   main.c
   console.c
@@ -309,6 +314,14 @@ target_link_libraries(eressea ${CURSES_LIBRARIES})
 add_definitions(-DUSE_CURSES)
 endif(CURSES_FOUND)
 
+if (EXPAT_FOUND)
+include_directories (${EXPAT_INCLUDE_DIRS})
+target_link_libraries(eressea ${EXPAT_LIBRARIES})
+target_link_libraries(convert ${EXPAT_LIBRARIES})
+target_link_libraries(test_eressea ${EXPAT_LIBRARIES})
+add_definitions(-DUSE_EXPAT)
+endif (EXPAT_FOUND)
+
 if (LIBXML2_FOUND)
 include_directories (${LIBXML2_INCLUDE_DIR})
 target_link_libraries(eressea ${LIBXML2_LIBRARIES})
diff --git a/src/exparse.c b/src/exparse.c
new file mode 100644
index 000000000..0a9722344
--- /dev/null
+++ b/src/exparse.c
@@ -0,0 +1,7 @@
+#include "exparse.h"
+
+#include <expat.h>
+
+int exparse_readfile(const char * filename) {
+    return 1;
+}
diff --git a/src/exparse.h b/src/exparse.h
new file mode 100644
index 000000000..9401addc0
--- /dev/null
+++ b/src/exparse.h
@@ -0,0 +1,3 @@
+#pragma once
+
+int exparse_readfile(const char * filename);
diff --git a/src/jsonconf.c b/src/jsonconf.c
index c14ac9216..4d84fc1ca 100644
--- a/src/jsonconf.c
+++ b/src/jsonconf.c
@@ -46,6 +46,9 @@ without prior permission by the authors of Eressea.
 #include "move.h"
 #include "prefix.h"
 #include "skill.h"
+#ifdef USE_EXPAT
+#include "exparse.h"
+#endif
 
 /* external libraries */
 #include <cJSON.h>
@@ -969,8 +972,16 @@ static int include_json(const char *uri) {
 static int include_xml(const char *uri) {
     char name[PATH_MAX];
     const char *filename = uri_to_file(uri, name, sizeof(name));
-    int err = read_xml(filename);
-    if (err < 0) {
+    int err;
+#ifdef USE_EXPAT
+    err = exparse_readfile(filename);
+    if (err != 0) {
+        err = read_xml(filename);
+    }
+#else
+    err = read_xml(filename);
+#endif
+    if (err != 0) {
         log_error("could not parse XML from %s", uri);
     }
     return err;

From b28cbd606d45b6c4ba2079ce8cd5a8075516ff84 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Tue, 24 Apr 2018 22:04:23 +0200
Subject: [PATCH 02/59] minimal expat parsing code

---
 src/exparse.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/src/exparse.c b/src/exparse.c
index 0a9722344..70328e0ae 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -1,7 +1,41 @@
 #include "exparse.h"
 
+#include "util/log.h"
+
 #include <expat.h>
 
 int exparse_readfile(const char * filename) {
-    return 1;
+    XML_Parser xp;
+    FILE *F;
+    int err = 1;
+    char buf[4096];
+
+    F = fopen(filename, "r");
+    if (!F) {
+        return 2;
+    }
+    xp = XML_ParserCreate("UTF-8");
+    for (;;) {
+        size_t len = (int) fread(buf, 1, sizeof(buf), F);
+        int done;
+        
+        if (ferror(F)) {
+            log_error("read error in %s", filename);
+            return -1;
+        }
+        done = feof(F);
+        if (XML_Parse(xp, buf, len, done) == XML_STATUS_ERROR) {
+            log_error("parse error at line %u of %s: %s", 
+                    XML_GetCurrentLineNumber(xp),
+                    filename,
+                    XML_ErrorString(XML_GetErrorCode(xp)));
+            return -1;
+        }
+        if (done) {
+            break;
+        }
+    }
+    XML_ParserFree(xp);
+    fclose(F);
+    return err;
 }

From c3b25328d35ece6ee82f4802f91725bb8a8aa2f6 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Tue, 24 Apr 2018 21:16:56 +0100
Subject: [PATCH 03/59] don't exist with a leak, fix MSVC compilation.

---
 src/exparse.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 70328e0ae..011212831 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -1,3 +1,6 @@
+#ifdef _MSC_VER
+#include <platform.h>
+#endif
 #include "exparse.h"
 
 #include "util/log.h"
@@ -21,7 +24,8 @@ int exparse_readfile(const char * filename) {
         
         if (ferror(F)) {
             log_error("read error in %s", filename);
-            return -1;
+            err = -2;
+            break;
         }
         done = feof(F);
         if (XML_Parse(xp, buf, len, done) == XML_STATUS_ERROR) {
@@ -29,7 +33,8 @@ int exparse_readfile(const char * filename) {
                     XML_GetCurrentLineNumber(xp),
                     filename,
                     XML_ErrorString(XML_GetErrorCode(xp)));
-            return -1;
+            err = -1;
+            break;
         }
         if (done) {
             break;

From 0b22b500139c4fc6d933fc8d61cd9ddad0eb62d5 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sat, 28 Apr 2018 11:38:11 +0200
Subject: [PATCH 04/59] the presspass is cursed, attribute needs to be on item,
 not resource.

---
 res/core/common/items.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/res/core/common/items.xml b/res/core/common/items.xml
index d04b6a252..67f2c1119 100644
--- a/res/core/common/items.xml
+++ b/res/core/common/items.xml
@@ -34,8 +34,8 @@
     <item weight="0" score="6000"/>
   </resource>
 
-  <resource name="presspass" cursed="yes">
-    <item weight="0" score="6000"/>
+  <resource name="presspass">
+    <item weight="0" score="6000" cursed="yes"/>
   </resource>
 
   <resource name="aurafocus">

From 08663b6eb5c47b76f2c684699bc73c5189030079 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sat, 28 Apr 2018 15:57:51 +0200
Subject: [PATCH 05/59] fix last commit. refactoring with the MSVC IDE is prone
 to errors.

---
 src/kernel/pathfinder.c | 36 ++++++++++++++++++------------------
 src/kernel/pathfinder.h |  4 ++--
 src/laws.c              |  6 +++---
 src/magic.c             |  6 +++---
 src/magic.h             |  2 +-
 src/monsters.c          |  8 ++++----
 src/report.c            | 34 +++++++++++++++++-----------------
 src/reports.c           | 22 +++++++++++-----------
 src/util/filereader.c   | 18 +++++++++---------
 src/util/strings.c      |  8 ++++----
 src/util/translation.c  |  6 +++---
 11 files changed, 75 insertions(+), 75 deletions(-)

diff --git a/src/kernel/pathfinder.c b/src/kernel/pathfinder.c
index 3c06fc3d7..61cead5fd 100644
--- a/src/kernel/pathfinder.c
+++ b/src/kernel/pathfinder.c
@@ -95,12 +95,12 @@ static void free_nodes(node * root)
     }
 }
 
-struct selist *regions_in_range(struct region *start, int maxdist,
+struct selist *regions_in_range(struct region *handle_start, int maxdist,
     bool(*allowed) (const struct region *, const struct region *))
 {
     selist * rlist = NULL;
-    node *root = new_node(start, 0, NULL);
-    node **end = &root->next;
+    node *root = new_node(handle_start, 0, NULL);
+    node **handle_end = &root->next;
     node *n = root;
 
     while (n != NULL) {
@@ -125,8 +125,8 @@ struct selist *regions_in_range(struct region *start, int maxdist,
             /* make sure we don't go here again, and put the region into the set for
                further BFS'ing */
             fset(rn, RF_MARK);
-            *end = new_node(rn, depth, n);
-            end = &(*end)->next;
+            *handle_end = new_node(rn, depth, n);
+            handle_end = &(*handle_end)->next;
         }
         n = n->next;
     }
@@ -135,17 +135,17 @@ struct selist *regions_in_range(struct region *start, int maxdist,
     return rlist;
 }
 
-static region **internal_path_find(region * start, const region * target,
+static region **internal_path_find(region * handle_start, const region * target,
     int maxlen, bool(*allowed) (const region *, const region *))
 {
     static region *path[MAXDEPTH + 2];    /* STATIC_RETURN: used for return, not across calls */
     direction_t d;
-    node *root = new_node(start, 0, NULL);
-    node **end = &root->next;
+    node *root = new_node(handle_start, 0, NULL);
+    node **handle_end = &root->next;
     node *n = root;
     bool found = false;
     assert(maxlen <= MAXDEPTH);
-    fset(start, RF_MARK);
+    fset(handle_start, RF_MARK);
 
     while (n != NULL) {
         region *r = n->r;
@@ -173,8 +173,8 @@ static region **internal_path_find(region * start, const region * target,
             }
             else {
                 fset(rn, RF_MARK);
-                *end = new_node(rn, depth, n);
-                end = &(*end)->next;
+                *handle_end = new_node(rn, depth, n);
+                handle_end = &(*handle_end)->next;
             }
         }
         if (found)
@@ -188,22 +188,22 @@ static region **internal_path_find(region * start, const region * target,
 }
 
 bool
-path_exists(region * start, const region * target, int maxlen,
+path_exists(region * handle_start, const region * target, int maxlen,
 bool(*allowed) (const region *, const region *))
 {
-    assert((!fval(start, RF_MARK) && !fval(target, RF_MARK))
+    assert((!fval(handle_start, RF_MARK) && !fval(target, RF_MARK))
         || !"Some Algorithm did not clear its RF_MARKs!");
-    if (start == target)
+    if (handle_start == target)
         return true;
-    if (internal_path_find(start, target, maxlen, allowed) != NULL)
+    if (internal_path_find(handle_start, target, maxlen, allowed) != NULL)
         return true;
     return false;
 }
 
-region **path_find(region * start, const region * target, int maxlen,
+region **path_find(region * handle_start, const region * target, int maxlen,
     bool(*allowed) (const region *, const region *))
 {
-    assert((!fval(start, RF_MARK) && !fval(target, RF_MARK))
+    assert((!fval(handle_start, RF_MARK) && !fval(target, RF_MARK))
         || !"Did you call path_init()?");
-    return internal_path_find(start, target, maxlen, allowed);
+    return internal_path_find(handle_start, target, maxlen, allowed);
 }
diff --git a/src/kernel/pathfinder.h b/src/kernel/pathfinder.h
index 682fa4d25..a6c583139 100644
--- a/src/kernel/pathfinder.h
+++ b/src/kernel/pathfinder.h
@@ -22,10 +22,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 extern "C" {
 #endif
 
-    extern struct region **path_find(struct region *start,
+    extern struct region **path_find(struct region *handle_start,
         const struct region *target, int maxlen,
         bool(*allowed) (const struct region *, const struct region *));
-    extern bool path_exists(struct region *start, const struct region *target,
+    extern bool path_exists(struct region *handle_start, const struct region *target,
         int maxlen, bool(*allowed) (const struct region *,
         const struct region *));
     extern bool allowed_swim(const struct region *src,
diff --git a/src/laws.c b/src/laws.c
index 1887d8657..15487ab47 100644
--- a/src/laws.c
+++ b/src/laws.c
@@ -4103,11 +4103,11 @@ static void reset_game(void)
 
 void turn_begin(void)
 {
-    int start = first_turn();
+    int handle_start = first_turn();
     assert(turn >= 0);
-    if (turn < start) {
+    if (turn < handle_start) {
         /* this should only happen during tests */
-        turn = start;
+        turn = handle_start;
     }
     ++turn;
     reset_game();
diff --git a/src/magic.c b/src/magic.c
index 1865b4f9e..0accc008d 100644
--- a/src/magic.c
+++ b/src/magic.c
@@ -2056,11 +2056,11 @@ void free_castorder(struct castorder *co)
 void add_castorder(spellrank * cll, castorder * co)
 {
     if (cll->begin == NULL) {
-        cll->end = &cll->begin;
+        cll->handle_end = &cll->begin;
     }
 
-    *cll->end = co;
-    cll->end = &co->next;
+    *cll->handle_end = co;
+    cll->handle_end = &co->next;
 
     return;
 }
diff --git a/src/magic.h b/src/magic.h
index ae43fd5af..4a00a7b13 100644
--- a/src/magic.h
+++ b/src/magic.h
@@ -272,7 +272,7 @@ extern "C" {
 
     typedef struct spellrank {
         struct castorder *begin;
-        struct castorder **end;
+        struct castorder **handle_end;
     } spellrank;
 
     struct castorder *create_castorder(struct castorder * co, struct unit *caster,
diff --git a/src/monsters.c b/src/monsters.c
index 9d113c0e9..46f63a92d 100644
--- a/src/monsters.c
+++ b/src/monsters.c
@@ -848,15 +848,15 @@ static double chaosfactor(region * r)
     return fval(r, RF_CHAOTIC) ? ((double)(1 + get_chaoscount(r)) / 1000.0) : 0.0;
 }
 
-static int nrand(int start, int sub)
+static int nrand(int handle_start, int sub)
 {
     int res = 0;
 
     do {
-        if (rng_int() % 100 < start)
+        if (rng_int() % 100 < handle_start)
             res++;
-        start -= sub;
-    } while (start > 0);
+        handle_start -= sub;
+    } while (handle_start > 0);
 
     return res;
 }
diff --git a/src/report.c b/src/report.c
index 319203e3b..9568d640a 100644
--- a/src/report.c
+++ b/src/report.c
@@ -181,7 +181,7 @@ paragraph(struct stream *out, const char *str, ptrdiff_t indent, int hanging_ind
     char marker)
 {
     size_t length = REPORTWIDTH;
-    const char *end, *begin, *mark = 0;
+    const char *handle_end, *begin, *mark = 0;
 
     if (!str) return;
     /* find out if there's a mark + indent already encoded in the string. */
@@ -200,7 +200,7 @@ paragraph(struct stream *out, const char *str, ptrdiff_t indent, int hanging_ind
     else {
         mark = &marker;
     }
-    begin = end = str;
+    begin = handle_end = str;
 
     do {
         const char *last_space = begin;
@@ -217,25 +217,25 @@ paragraph(struct stream *out, const char *str, ptrdiff_t indent, int hanging_ind
         else {
             write_spaces(out, indent + hanging_indent);
         }
-        while (*end && end <= begin + length - indent) {
-            if (*end == ' ') {
-                last_space = end;
+        while (*handle_end && handle_end <= begin + length - indent) {
+            if (*handle_end == ' ') {
+                last_space = handle_end;
             }
-            ++end;
+            ++handle_end;
         }
-        if (*end == 0)
-            last_space = end;
+        if (*handle_end == 0)
+            last_space = handle_end;
         if (last_space == begin) {
             /* there was no space in this line. clip it */
-            last_space = end;
+            last_space = handle_end;
         }
         swrite(begin, sizeof(char), last_space - begin, out);
         begin = last_space;
         while (*begin == ' ') {
             ++begin;
         }
-        if (begin > end)
-            begin = end;
+        if (begin > handle_end)
+            begin = handle_end;
         sputs("", out);
     } while (*begin);
 }
@@ -1939,7 +1939,7 @@ static void nr_paragraph(struct stream *out, message * m, faction * f)
 
 typedef struct cb_data {
     struct stream *out;
-    char *start, *writep;
+    char *handle_start, *writep;
     size_t size;
     const faction *f;
     int maxtravel, counter;
@@ -1948,7 +1948,7 @@ typedef struct cb_data {
 static void init_cb(cb_data *data, struct stream *out, char *buffer, size_t size, const faction *f) {
     data->out = out;
     data->writep = buffer;
-    data->start = buffer;
+    data->handle_start = buffer;
     data->size = size;
     data->f = f;
     data->maxtravel = 0;
@@ -1965,7 +1965,7 @@ static void cb_write_travelthru(region *r, unit *u, void *cbdata) {
     if (travelthru_cansee(r, f, u)) {
         ++data->counter;
         do {
-            size_t len, size = data->size - (data->writep - data->start);
+            size_t len, size = data->size - (data->writep - data->handle_start);
             const char *str;
             char *writep = data->writep;
 
@@ -2000,13 +2000,13 @@ static void cb_write_travelthru(region *r, unit *u, void *cbdata) {
             if (len >= size || data->counter == data->maxtravel) {
                 /* buffer is full */
                 *writep = 0;
-                paragraph(data->out, data->start, 0, 0, 0);
-                data->writep = data->start;
+                paragraph(data->out, data->handle_start, 0, 0, 0);
+                data->writep = data->handle_start;
                 if (data->counter == data->maxtravel) {
                     break;
                 }
             }
-        } while (data->writep == data->start);
+        } while (data->writep == data->handle_start);
     }
 }
 
diff --git a/src/reports.c b/src/reports.c
index f5b7f5531..568c66183 100644
--- a/src/reports.c
+++ b/src/reports.c
@@ -2242,7 +2242,7 @@ static void eval_regions(struct opstack **stack, const void *userdata)
 {                               /* order -> string */
     const faction *report = (const faction *)userdata;
     int i = opop(stack).i;
-    int end, begin = opop(stack).i;
+    int handle_end, begin = opop(stack).i;
     const arg_regions *aregs = (const arg_regions *)opop(stack).v;
     char buf[256];
     size_t size = sizeof(buf) - 1;
@@ -2250,19 +2250,19 @@ static void eval_regions(struct opstack **stack, const void *userdata)
     char *bufp = buf;
 
     if (aregs == NULL) {
-        end = begin;
+        handle_end = begin;
     }
     else {
         if (i >= 0)
-            end = begin + i;
+            handle_end = begin + i;
         else
-            end = aregs->nregions + i;
+            handle_end = aregs->nregions + i;
     }
-    for (i = begin; i < end; ++i) {
+    for (i = begin; i < handle_end; ++i) {
         const char *rname = (const char *)regionname(aregs->regions[i], report);
         bufp = STRLCPY(bufp, rname, size);
 
-        if (i + 1 < end && size > 2) {
+        if (i + 1 < handle_end && size > 2) {
             strcat(bufp, ", ");
             bufp += 2;
             size -= 2;
@@ -2295,9 +2295,9 @@ static void eval_trail(struct opstack **stack, const void *userdata)
 #endif
 
     if (aregs != NULL) {
-        int i, end = 0, begin = 0;
-        end = aregs->nregions;
-        for (i = begin; i < end; ++i) {
+        int i, handle_end = 0, begin = 0;
+        handle_end = aregs->nregions;
+        for (i = begin; i < handle_end; ++i) {
             region *r = aregs->regions[i];
             const char *trail = trailinto(r, lang);
             const char *rn = f_regionid_s(r, report);
@@ -2305,10 +2305,10 @@ static void eval_trail(struct opstack **stack, const void *userdata)
             if (wrptr(&bufp, &size, snprintf(bufp, size, trail, rn)) != 0)
                 WARN_STATIC_BUFFER();
 
-            if (i + 2 < end) {
+            if (i + 2 < handle_end) {
                 bufp = STRLCPY(bufp, ", ", size);
             }
-            else if (i + 1 < end) {
+            else if (i + 1 < handle_end) {
                 bufp = STRLCPY(bufp, LOC(lang, "list_and"), size);
             }
         }
diff --git a/src/util/filereader.c b/src/util/filereader.c
index d36d3ca71..e477b445c 100644
--- a/src/util/filereader.c
+++ b/src/util/filereader.c
@@ -136,11 +136,11 @@ static const char *getbuf_latin1(FILE * F)
                 continue;
             }
             else if (c == CONTINUE_CHAR) {
-                const char *end = ++bp;
-                while (*end && isspace(*(unsigned char *)end))
-                    ++end;                /* eatwhite */
-                if (*end == '\0') {
-                    bp = end;
+                const char *handle_end = ++bp;
+                while (*handle_end && isspace(*(unsigned char *)handle_end))
+                    ++handle_end;                /* eatwhite */
+                if (*handle_end == '\0') {
+                    bp = handle_end;
                     cont = true;
                     continue;
                 }
@@ -303,11 +303,11 @@ static const char *getbuf_utf8(FILE * F)
             }
             else {
                 if (*bp == CONTINUE_CHAR) {
-                    const char *end;
+                    const char *handle_end;
                     eatwhite(bp + 1, &white);
-                    end = bp + 1 + white;
-                    if (*end == '\0') {
-                        bp = end;
+                    handle_end = bp + 1 + white;
+                    if (*handle_end == '\0') {
+                        bp = handle_end;
                         cont = true;
                         continue;
                     }
diff --git a/src/util/strings.c b/src/util/strings.c
index 4959fba6c..81fdc3713 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -157,13 +157,13 @@ unsigned int str_hash(const char *s)
 const char *str_escape(const char *str, char *buffer,
     size_t len)
 {
-    const char *start = strchr(str, '\"');
-    if (!start) start = strchr(str, '\\');
+    const char *handle_start = strchr(str, '\"');
+    if (!handle_start) handle_start = strchr(str, '\\');
     assert(buffer);
-    if (start) {
+    if (handle_start) {
         const char *p;
         char *o;
-        size_t skip = start - str;
+        size_t skip = handle_start - str;
 
         if (skip > len) {
             skip = len;
diff --git a/src/util/translation.c b/src/util/translation.c
index da26806fe..4d032911e 100644
--- a/src/util/translation.c
+++ b/src/util/translation.c
@@ -77,7 +77,7 @@ void opstack_push(opstack ** stackp, variant data)
 #define BBUFSIZE 0x10000
 static struct {
     char *begin;
-    char *end;
+    char *handle_end;
     char *last;
     char *current;
 } buffer;
@@ -88,9 +88,9 @@ char *balloc(size_t size)
     if (!init) {
         init = 1;
         buffer.current = buffer.begin = malloc(BBUFSIZE * sizeof(char));
-        buffer.end = buffer.begin + BBUFSIZE;
+        buffer.handle_end = buffer.begin + BBUFSIZE;
     }
-    assert(buffer.current + size <= buffer.end || !"balloc is out of memory");
+    assert(buffer.current + size <= buffer.handle_end || !"balloc is out of memory");
     buffer.last = buffer.current;
     buffer.current += size;
     return buffer.last;

From edadf2cbabef1432f064e423499a985cf55ab97c Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sat, 28 Apr 2018 15:58:14 +0200
Subject: [PATCH 06/59] exparse: parse (most of) the resource data.

---
 src/exparse.c          | 317 ++++++++++++++++++++++++++++++++++++++++-
 src/kernel/item.c      |  10 +-
 src/kernel/item.h      |   3 +-
 src/kernel/region.c    |  12 +-
 src/kernel/resources.c |  18 +--
 src/spells/unitcurse.c |  18 +--
 src/xmlreader.c        |  31 +++-
 7 files changed, 374 insertions(+), 35 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 011212831..44593f3cf 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -3,21 +3,330 @@
 #endif
 #include "exparse.h"
 
+#include "kernel/build.h"
+#include "kernel/item.h"
+#include "kernel/resources.h"
+
 #include "util/log.h"
 
 #include <expat.h>
 
+#include <assert.h>
+#include <string.h>
+
+#ifdef XML_LARGE_SIZE
+# if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400
+#  define XML_FMT_INT_MOD "I64"
+# else
+#  define XML_FMT_INT_MOD "ll"
+# endif
+#else
+# define XML_FMT_INT_MOD "l"
+#endif
+
+#ifdef XML_UNICODE_WCHAR_T
+# define XML_FMT_STR "ls"
+#else
+# define XML_FMT_STR "s"
+#endif
+
+enum {
+    EXP_UNKNOWN,
+
+    EXP_RESOURCES,
+    EXP_BUILDINGS,
+    EXP_SHIPS,
+    EXP_MESSAGES,
+    EXP_STRINGS,
+};
+
+typedef struct userdata {
+    int type;
+    int depth;
+    int errors;
+    XML_Char *cdata;
+    size_t clength;
+    void *object;
+} userdata;
+
+static int xml_strcmp(const XML_Char *xs, const char *cs) {
+    return strcmp(xs, cs);
+}
+
+static const char * attr_get(const XML_Char **attr, const char *key) {
+    int i;
+    for (i = 0; attr[i]; i += 2) {
+        if (xml_strcmp(attr[i], key) == 0) {
+            return (const char *)attr[i + 1];
+        }
+    }
+    return NULL;
+}
+
+static bool xml_bool(const XML_Char *val) {
+    if (xml_strcmp(val, "yes") == 0) return true;
+    if (xml_strcmp(val, "true") == 0) return true;
+    if (xml_strcmp(val, "1") == 0) return true;
+    return false;
+}
+
+static int xml_int(const XML_Char *val) {
+    return atoi((const char *)val);
+}
+
+static bool attr_bool(XML_Char **pair, const char *key) {
+    if (xml_strcmp(pair[0], key) == 0) {
+        return xml_bool(pair[1]);
+    }
+    return false;
+}
+
+static void handle_bad_input(userdata *ud, const XML_Char *el, const XML_Char *attr) {
+    if (attr) {
+        log_error("unknown attribute in <%s>: %s", (const char *)el, (const char *)attr);
+    }
+    else {
+        log_error("unexpected element <%s>", (const char *)el);
+    }
+    ++ud->errors;
+}
+
+static bool handle_flag(int *flags, const XML_Char **pair, const char *names[]) {
+    int i;
+    for (i = 0; names[i]; ++i) {
+        if (xml_strcmp(pair[0], names[i]) == 0) {
+            if (xml_bool(pair[1])) {
+                *flags |= (1 << i);
+            }
+            else {
+                *flags &= ~(1 << i);
+            }
+            return true;
+        }
+    }
+    return false;
+}
+
+static void handle_resource(userdata *ud, const XML_Char *el, const XML_Char **attr) {
+    const char *flag_names[] = { "item", "limited", "pooled", NULL };
+    int i;
+    const char *name = NULL, *appear = NULL;
+    int flags = RTF_POOLED;
+    bool material = false;
+    (void)el;
+    for (i = 0; attr[i]; i += 2) {
+        if (xml_strcmp(attr[i], "name") == 0) {
+            name = (const char *)attr[i + 1];
+        }
+        else if (xml_strcmp(attr[i], "appearance") == 0) {
+            /* TODO: appearance should be a property of item, not resource */
+            appear = (const char *)attr[i + 1];
+            flags |= RTF_ITEM;
+        }
+        else if (xml_strcmp(attr[i], "material") == 0) {
+            /* TODO: appearance should be a property of item, not resource */
+            material = xml_bool(attr[i + 1]);
+        }
+        else if (!handle_flag(&flags, attr + i, flag_names)) {
+            handle_bad_input(ud, el, attr[i]);
+        }
+    }
+    if (name) {
+        resource_type *rtype = rt_get_or_create(name);
+        rtype->flags = flags;
+        if (appear) {
+            /* TODO: appearance should be a property of item, not resource */
+            rtype->itype = it_get_or_create(rtype);
+            it_set_appearance(rtype->itype, appear);
+        }
+        if (material) {
+            rmt_create(rtype);
+        }
+        ud->object = rtype;
+    }
+}
+
+static void handle_item(userdata *ud, const XML_Char *el, const XML_Char **attr) {
+    const char *flag_names[] = { "herb", "cursed", "notlost", "big", "animal", "vehicle", "use", NULL };
+    int i, flags = ITF_NONE;
+    resource_type *rtype = (resource_type *)ud->object;
+    item_type * itype = rtype->itype;
+    assert(rtype);
+    if (!itype) {
+        itype = it_get_or_create(rtype);
+    }
+    for (i = 0; attr[i]; i += 2) {
+        if (xml_strcmp(attr[i], "weight") == 0) {
+            itype->weight = xml_int(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "capacity") == 0) {
+            itype->capacity = xml_int(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "score") == 0) {
+            itype->score = xml_int(attr[i + 1]);
+        }
+        else if (!handle_flag(&flags, attr + i, flag_names)) {
+            handle_bad_input(ud, el, attr[i]);
+        }
+    }
+    itype->flags = flags;
+}
+
+static void XMLCALL handle_resources(userdata *ud, const XML_Char *el, const XML_Char **attr) {
+    resource_type *rtype = (resource_type *)ud->object;
+    if (xml_strcmp(el, "resource") == 0) {
+        handle_resource(ud, el, attr);
+    }
+    else if (rtype) {
+        if (xml_strcmp(el, "item") == 0) {
+            assert(rtype);
+            handle_item(ud, el, attr);
+        }
+        else if (xml_strcmp(el, "function") == 0) {
+            assert(rtype);
+            /* TODO */
+        }
+        else if (rtype->itype) {
+            item_type *itype = rtype->itype;
+            if (xml_strcmp(el, "construction") == 0) {
+                construction *con = calloc(sizeof(construction), 1);
+                int i;
+                for (i = 0; attr[i]; i += 2) {
+                    if (xml_strcmp(attr[i], "skill") == 0) {
+                        con->skill = findskill((const char *)attr[i + 1]);
+                    }
+                    else if (xml_strcmp(attr[i], "maxsize") == 0) {
+                        con->maxsize = xml_int(attr[i + 1]);
+                    }
+                    else if (xml_strcmp(attr[i], "reqsize") == 0) {
+                        con->reqsize = xml_int(attr[i + 1]);
+                    }
+                    else if (xml_strcmp(attr[i], "minskill") == 0) {
+                        con->minskill = xml_int(attr[i + 1]);
+                    }
+                    else {
+                        handle_bad_input(ud, el, attr[i]);
+                    }
+                }
+                itype->construction = con;
+            }
+            else if (xml_strcmp(el, "requirement") == 0) {
+                assert(itype->construction);
+                /* TODO */
+            }
+            else if (xml_strcmp(el, "luxury") == 0) {
+                /* TODO */
+            }
+            else if (xml_strcmp(el, "potion") == 0) {
+                /* TODO */
+            }
+            else if (xml_strcmp(el, "armor") == 0) {
+                /* TODO */
+                rtype->atype = new_armortype(itype, 0.0, frac_zero, 0, 0);
+            }
+            else if (xml_strcmp(el, "weapon") == 0) {
+                rtype->wtype = new_weapontype(itype, 0, frac_zero, NULL, 0, 0, 0, SK_MELEE);
+                /* TODO */
+            }
+            else if (xml_strcmp(el, "damage") == 0) {
+                assert(rtype->wtype);
+                /* TODO */
+            }
+            else {
+                handle_bad_input(ud, el, NULL);
+            }
+        }
+        else {
+            handle_bad_input(ud, el, NULL);
+        }
+    }
+    else {
+        handle_bad_input(ud, el, NULL);
+    }
+}
+
+static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char **attr) {
+    userdata *ud = (userdata *)data;
+    if (ud->depth == 0) {
+        ud->type = EXP_UNKNOWN;
+        if (xml_strcmp(el, "eressea") != 0) {
+            handle_bad_input(ud, el, NULL);
+        }
+    }
+    else if (ud->depth == 1) {
+        if (xml_strcmp(el, "resources") == 0) {
+            ud->type = EXP_RESOURCES;
+        }
+        else if (xml_strcmp(el, "buildings") == 0) {
+            ud->type = EXP_BUILDINGS;
+        }
+        else if (xml_strcmp(el, "ships") == 0) {
+            ud->type = EXP_SHIPS;
+        }
+        else if (xml_strcmp(el, "messages") == 0) {
+            ud->type = EXP_MESSAGES;
+        }
+        else if (xml_strcmp(el, "strings") == 0) {
+            ud->type = EXP_STRINGS;
+        }
+        else {
+            handle_bad_input(ud, el, NULL);
+        }
+    }
+    else {
+        switch (ud->type) {
+        case EXP_RESOURCES:
+            handle_resources(ud, el, attr);
+        default:
+            /* not implemented */
+            handle_bad_input(ud, el, NULL);
+        }
+    }
+    ++ud->depth;
+}
+
+static void XMLCALL handle_end(void *data, const XML_Char *el) {
+    userdata *ud = (userdata *)data;
+    --ud->depth;
+    if (ud->cdata) {
+        free(ud->cdata);
+        ud->cdata = NULL;
+        ud->clength = 0;
+    }
+    if (ud->depth == 0) {
+        ud->type = EXP_UNKNOWN;
+    }
+}
+
+static void XMLCALL handle_data(void *data, const XML_Char *xs, int len) {
+    userdata *ud = (userdata *)data;
+    if (len > 0) {
+        if (ud->type == EXP_MESSAGES && ud->depth == 4) {
+            size_t bytes = (size_t)len;
+            ud->cdata = realloc(ud->cdata, ud->clength + bytes);
+            memcpy(ud->cdata + ud->clength, xs, bytes);
+            ud->clength = ud->clength + bytes;
+        }
+    }
+}
+
+
 int exparse_readfile(const char * filename) {
     XML_Parser xp;
     FILE *F;
     int err = 1;
     char buf[4096];
+    userdata ud;
 
     F = fopen(filename, "r");
     if (!F) {
         return 2;
     }
     xp = XML_ParserCreate("UTF-8");
+    XML_SetElementHandler(xp, handle_start, handle_end);
+    XML_SetCharacterDataHandler(xp, handle_data);
+    XML_SetUserData(xp, &ud);
+    memset(&ud, 0, sizeof(ud));
     for (;;) {
         size_t len = (int) fread(buf, 1, sizeof(buf), F);
         int done;
@@ -29,7 +338,7 @@ int exparse_readfile(const char * filename) {
         }
         done = feof(F);
         if (XML_Parse(xp, buf, len, done) == XML_STATUS_ERROR) {
-            log_error("parse error at line %u of %s: %s", 
+            log_error("parse error at line %" XML_FMT_INT_MOD " of %s: %" XML_FMT_STR,
                     XML_GetCurrentLineNumber(xp),
                     filename,
                     XML_ErrorString(XML_GetErrorCode(xp)));
@@ -40,7 +349,11 @@ int exparse_readfile(const char * filename) {
             break;
         }
     }
+    assert(ud.depth == 0);
     XML_ParserFree(xp);
     fclose(F);
-    return err;
+    if (err != 0) {
+        return err;
+    }
+    return ud.errors;
 }
diff --git a/src/kernel/item.c b/src/kernel/item.c
index ab6ad8c8d..a573dc4ba 100644
--- a/src/kernel/item.c
+++ b/src/kernel/item.c
@@ -916,7 +916,11 @@ static void free_itype(item_type *itype) {
     free(itype);
 }
 
-static void free_wtype(weapon_type *wtype) {
+void free_atype(armor_type *atype) {
+    free(atype);
+}
+
+void free_wtype(weapon_type *wtype) {
     assert(wtype);
     free(wtype->damage[0]);
     free(wtype->damage[1]);
@@ -931,7 +935,9 @@ void free_rtype(resource_type *rtype) {
     if (rtype->itype) {
         free_itype(rtype->itype);
     }
-    free(rtype->atype);
+    if (rtype->atype) {
+        free_atype(rtype->atype);
+    }
     free(rtype->modifiers);
     free(rtype->raw);
     free(rtype->_name);
diff --git a/src/kernel/item.h b/src/kernel/item.h
index e7bfef7cc..9079369e8 100644
--- a/src/kernel/item.h
+++ b/src/kernel/item.h
@@ -224,9 +224,10 @@ extern "C" {
     weapon_type *new_weapontype(item_type * itype, int wflags,
         variant magres, const char *damage[], int offmod, int defmod, int reload,
         skill_t sk);
+    void free_wtype(struct weapon_type *wtype);
     armor_type *new_armortype(item_type * itype, double penalty,
         variant magres, int prot, unsigned int flags);
-
+    void free_atype(struct armor_type *wtype);
     /* these constants are used with get_resourcetype.
      * The order of the enum is not important for stored data.
      * The resourcenames array must be updated to match.
diff --git a/src/kernel/region.c b/src/kernel/region.c
index 790a8341c..7ceab2f18 100644
--- a/src/kernel/region.c
+++ b/src/kernel/region.c
@@ -971,16 +971,16 @@ static char *makename(void)
     size_t nk, ne, nv, ns;
     static char name[16];
     const char *kons = "bcdfghklmnprstvwz",
-        *start = "bcdgtskpvfr",
-        *end = "nlrdst",
+        *handle_start = "bcdgtskpvfr",
+        *handle_end = "nlrdst",
         *vowels = "aaaaaaaaaaaeeeeeeeeeeeeiiiiiiiiiiioooooooooooouuuuuuuuuuyy";
 
     /* const char * vowels_latin1 = "aaaaaaaaa��eeeeeeeee���iiiiiiiii��ooooooooo���uuuuuuuuu�yy"; */
 
     nk = strlen(kons);
-    ne = strlen(end);
+    ne = strlen(handle_end);
     nv = strlen(vowels);
-    ns = strlen(start);
+    ns = strlen(handle_start);
 
     for (s = rng_int() % 3 + 2; s > 0; s--) {
         int v;
@@ -991,7 +991,7 @@ static char *makename(void)
         }
         else {
             k = rng_int() % (int)ns;
-            name[p] = start[k];
+            name[p] = handle_start[k];
             p++;
         }
         v = rng_int() % (int)nv;
@@ -999,7 +999,7 @@ static char *makename(void)
         p++;
         if (rng_int() % 3 == 2 || s == 1) {
             e = rng_int() % (int)ne;
-            name[p] = end[e];
+            name[p] = handle_end[e];
             p++;
             x = 1;
         }
diff --git a/src/kernel/resources.c b/src/kernel/resources.c
index bcf26efb3..231b763f8 100644
--- a/src/kernel/resources.c
+++ b/src/kernel/resources.c
@@ -180,15 +180,15 @@ struct rawmaterial_type *rmt_create(struct resource_type *rtype)
 {
     rawmaterial_type *rmtype;
 
-    assert(!rtype->raw);
-    assert(!rtype->itype || rtype->itype->construction);
-    rmtype = rtype->raw = malloc(sizeof(rawmaterial_type));
-    rmtype->rtype = rtype;
-    rmtype->terraform = terraform_default;
-    rmtype->update = NULL;
-    rmtype->use = use_default;
-    rmtype->visible = visible_default;
-    return rmtype;
+    if (!rtype->raw) {
+        rmtype = rtype->raw = malloc(sizeof(rawmaterial_type));
+        rmtype->rtype = rtype;
+        rmtype->terraform = terraform_default;
+        rmtype->update = NULL;
+        rmtype->use = use_default;
+        rmtype->visible = visible_default;
+    }
+    return rtype->raw;
 }
 
 int limit_resource(const struct region *r, const resource_type *rtype)
diff --git a/src/spells/unitcurse.c b/src/spells/unitcurse.c
index 6fc979e38..a99eb082c 100644
--- a/src/spells/unitcurse.c
+++ b/src/spells/unitcurse.c
@@ -232,7 +232,7 @@ static message *cinfo_sparkle(const void *obj, objtype_t typ, const curse * c,
         "sparkle_18",
         NULL,                       /* end draig */
     };
-    int m, begin = 0, end = 0;
+    int m, begin = 0, handle_end = 0;
     unit *u;
     UNUSED_ARG(typ);
 
@@ -243,18 +243,18 @@ static message *cinfo_sparkle(const void *obj, objtype_t typ, const curse * c,
         return NULL;
 
     for (m = 0; m != c->magician->faction->magiegebiet; ++m) {
-        while (effects[end] != NULL)
-            ++end;
-        begin = end + 1;
-        end = begin;
+        while (effects[handle_end] != NULL)
+            ++handle_end;
+        begin = handle_end + 1;
+        handle_end = begin;
     }
 
-    while (effects[end] != NULL)
-        ++end;
-    if (end == begin)
+    while (effects[handle_end] != NULL)
+        ++handle_end;
+    if (handle_end == begin)
         return NULL;
     else {
-        int index = begin + curse_geteffect_int(c) % (end - begin);
+        int index = begin + curse_geteffect_int(c) % (handle_end - begin);
         return msg_message(mkname("curseinfo", effects[index]), "unit id", u,
             c->no);
     }
diff --git a/src/xmlreader.c b/src/xmlreader.c
index 66b04e611..a157569fd 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -559,8 +559,7 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype)
     assert(sk != NOSKILL);
     xmlFree(propValue);
 
-    wtype =
-        new_weapontype(itype, flags, magres, NULL, offmod, defmod, reload, sk);
+    wtype = new_weapontype(itype, flags, magres, NULL, offmod, defmod, reload, sk);
 
     /* reading weapon/damage */
     xpath->node = node;
@@ -712,7 +711,14 @@ static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
         flags |= ITF_ANIMAL;
     if (xml_bvalue(node, "vehicle", false))
         flags |= ITF_VEHICLE;
+
     itype = rtype->itype ? rtype->itype : it_get_or_create(rtype);
+    /* exparse: recreate child data. */
+    if (itype->construction) {
+        free_construction(itype->construction);
+        itype->construction = NULL;
+    }
+
     itype->weight = xml_ivalue(node, "weight", 0);
     itype->capacity = xml_ivalue(node, "capacity", 0);
     mask_races(node, "allow", &itype->mask_allow);
@@ -823,7 +829,18 @@ static int parse_resources(xmlDocPtr doc)
                 log_error("invalid resource %d has no name", i);
                 continue;
             }
+
             rtype = rt_get_or_create((const char *)name);
+            /* exparse: recreate child data. */
+            if (rtype->atype) {
+                free_atype(rtype->atype);
+                rtype->atype = NULL;
+            }
+            if (rtype->wtype) {
+                free_wtype(rtype->wtype);
+                rtype->wtype = NULL;
+            }
+
             rtype->flags |= flags;
             xmlFree(name);
 
@@ -858,10 +875,6 @@ static int parse_resources(xmlDocPtr doc)
             }
             xmlXPathFreeObject(result);
 
-            if (xml_bvalue(node, "material", false)) {
-                rmt_create(rtype);
-            }
-
             if (xml_bvalue(node, "limited", false)) {
                 rtype->flags |= RTF_LIMITED;
             }
@@ -869,6 +882,7 @@ static int parse_resources(xmlDocPtr doc)
             result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
             rtype->modifiers = xml_readmodifiers(result, node);
             xmlXPathFreeObject(result);
+
             /* reading eressea/resources/resource/resourcelimit/function */
             xpath->node = node;
             result = xmlXPathEvalExpression(BAD_CAST "resourcelimit/function", xpath);
@@ -889,6 +903,11 @@ static int parse_resources(xmlDocPtr doc)
                 }
             }
             xmlXPathFreeObject(result);
+
+            if (xml_bvalue(node, "material", false)) {
+                assert(!rtype->itype || rtype->itype->construction);
+                rmt_create(rtype);
+            }
         }
     }
     xmlXPathFreeObject(resources);

From 03cff6d595bbc72d386840e2584ac2357afae27c Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sat, 28 Apr 2018 16:14:32 +0200
Subject: [PATCH 07/59] extract rc_mask, add it to exparse code.

---
 src/exparse.c          | 14 ++++++++++++++
 src/kernel/race.c      | 17 +++++++++++++++++
 src/kernel/race.h      |  2 ++
 src/kernel/race.test.c | 15 +++++++++++++++
 src/xmlreader.c        | 13 +------------
 5 files changed, 49 insertions(+), 12 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 44593f3cf..5b8b2a279 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -5,6 +5,7 @@
 
 #include "kernel/build.h"
 #include "kernel/item.h"
+#include "kernel/race.h"
 #include "kernel/resources.h"
 
 #include "util/log.h"
@@ -156,6 +157,7 @@ static void handle_item(userdata *ud, const XML_Char *el, const XML_Char **attr)
         itype = it_get_or_create(rtype);
     }
     for (i = 0; attr[i]; i += 2) {
+        char buffer[64];
         if (xml_strcmp(attr[i], "weight") == 0) {
             itype->weight = xml_int(attr[i + 1]);
         }
@@ -165,6 +167,18 @@ static void handle_item(userdata *ud, const XML_Char *el, const XML_Char **attr)
         else if (xml_strcmp(attr[i], "score") == 0) {
             itype->score = xml_int(attr[i + 1]);
         }
+        else if (xml_strcmp(attr[i], "allow") == 0) {
+            size_t len = strlen(attr[i + 1]);
+            assert(len < sizeof(buffer));
+            memcpy(buffer, attr[i + 1], len + 1);
+            itype->mask_allow = rc_mask(buffer);
+        }
+        else if (xml_strcmp(attr[i], "deny") == 0) {
+            size_t len = strlen(attr[i + 1]);
+            assert(len < sizeof(buffer));
+            memcpy(buffer, attr[i + 1], len + 1);
+            itype->mask_deny = rc_mask(buffer);
+        }
         else if (!handle_flag(&flags, attr + i, flag_names)) {
             handle_bad_input(ud, el, attr[i]);
         }
diff --git a/src/kernel/race.c b/src/kernel/race.c
index edf415223..c9299d5bd 100644
--- a/src/kernel/race.c
+++ b/src/kernel/race.c
@@ -574,3 +574,20 @@ struct race * read_race_reference(struct storage *store)
 void register_race_function(race_func func, const char *name) {
     register_function((pf_generic)func, name);
 }
+
+static int race_mask = 1;
+
+int rc_mask(char *list) {
+    int mask = 0;
+    char * tok = strtok(list, " ,");
+    while (tok) {
+        race * rc = rc_get_or_create(tok);
+        if (!rc->mask_item) {
+            rc->mask_item = race_mask;
+            race_mask = race_mask << 1;
+        }
+        mask |= rc->mask_item;
+        tok = strtok(NULL, " ,");
+    }
+    return mask;
+}
diff --git a/src/kernel/race.h b/src/kernel/race.h
index 1203eaed2..042cb5e78 100644
--- a/src/kernel/race.h
+++ b/src/kernel/race.h
@@ -197,6 +197,8 @@ extern "C" {
 #define MIGRANTS_NONE 0
 #define MIGRANTS_LOG10 1
     int rc_migrants_formula(const race *rc);
+    
+    int rc_mask(char *list);
 
     /* Flags. Do not reorder these without changing json_race() in jsonconf.c */
 #define RCF_NPC            (1<<0)   /* cannot be the race for a player faction (and other limits?) */
diff --git a/src/kernel/race.test.c b/src/kernel/race.test.c
index dcb4ce6f7..2f34c127e 100644
--- a/src/kernel/race.test.c
+++ b/src/kernel/race.test.c
@@ -11,6 +11,7 @@
 #include <CuTest.h>
 
 #include <stdlib.h>
+#include <string.h>
 #include <limits.h>
 #include <assert.h>
 
@@ -172,6 +173,19 @@ static void test_racename(CuTest *tc) {
     test_teardown();
 }
 
+static void test_rc_mask(CuTest *tc) {
+    int mask;
+    char list[64];
+    test_setup();
+    strcpy(list, "goblin dwarf");
+    mask = rc_mask(list);
+    CuAssertIntEquals(tc, 3, mask);
+    CuAssertStrEquals(tc, "goblin", list);
+    mask = rc_mask(list);
+    CuAssertIntEquals(tc, 1, mask);
+    test_teardown();
+}
+
 CuSuite *get_race_suite(void)
 {
     CuSuite *suite = CuSuiteNew();
@@ -180,6 +194,7 @@ CuSuite *get_race_suite(void)
     SUITE_ADD_TEST(suite, test_rc_name);
     SUITE_ADD_TEST(suite, test_rc_defaults);
     SUITE_ADD_TEST(suite, test_rc_find);
+    SUITE_ADD_TEST(suite, test_rc_mask);
     SUITE_ADD_TEST(suite, test_rc_set_param);
     SUITE_ADD_TEST(suite, test_rc_can_use);
     SUITE_ADD_TEST(suite, test_racename);
diff --git a/src/xmlreader.c b/src/xmlreader.c
index a157569fd..111ce624e 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -667,23 +667,12 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype)
     return wtype;
 }
 
-static int race_mask = 1;
-
 static void mask_races(xmlNodePtr node, const char *key, int *maskp) {
     xmlChar *propValue = xmlGetProp(node, BAD_CAST key);
     int mask = 0;
     assert(maskp);
     if (propValue) {
-        char * tok = strtok((char *)propValue, " ,");
-        while (tok) {
-            race * rc = rc_get_or_create(tok);
-            if (!rc->mask_item) {
-                rc->mask_item = race_mask;
-                race_mask = race_mask << 1;
-            }
-            mask |= rc->mask_item;
-            tok = strtok(NULL, " ,");
-        }
+        mask = rc_mask((char *)propValue);
         xmlFree(propValue);
     }
     *maskp = mask;

From ff4bae4da113aff14846fbe96dd70222f2441c66 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sat, 28 Apr 2018 17:52:48 +0200
Subject: [PATCH 08/59] delete unused static functions.

---
 src/exparse.c | 23 +++--------------------
 1 file changed, 3 insertions(+), 20 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 5b8b2a279..afaa3daf8 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -54,16 +54,6 @@ static int xml_strcmp(const XML_Char *xs, const char *cs) {
     return strcmp(xs, cs);
 }
 
-static const char * attr_get(const XML_Char **attr, const char *key) {
-    int i;
-    for (i = 0; attr[i]; i += 2) {
-        if (xml_strcmp(attr[i], key) == 0) {
-            return (const char *)attr[i + 1];
-        }
-    }
-    return NULL;
-}
-
 static bool xml_bool(const XML_Char *val) {
     if (xml_strcmp(val, "yes") == 0) return true;
     if (xml_strcmp(val, "true") == 0) return true;
@@ -75,13 +65,6 @@ static int xml_int(const XML_Char *val) {
     return atoi((const char *)val);
 }
 
-static bool attr_bool(XML_Char **pair, const char *key) {
-    if (xml_strcmp(pair[0], key) == 0) {
-        return xml_bool(pair[1]);
-    }
-    return false;
-}
-
 static void handle_bad_input(userdata *ud, const XML_Char *el, const XML_Char *attr) {
     if (attr) {
         log_error("unknown attribute in <%s>: %s", (const char *)el, (const char *)attr);
@@ -125,7 +108,6 @@ static void handle_resource(userdata *ud, const XML_Char *el, const XML_Char **a
             flags |= RTF_ITEM;
         }
         else if (xml_strcmp(attr[i], "material") == 0) {
-            /* TODO: appearance should be a property of item, not resource */
             material = xml_bool(attr[i + 1]);
         }
         else if (!handle_flag(&flags, attr + i, flag_names)) {
@@ -229,7 +211,7 @@ static void XMLCALL handle_resources(userdata *ud, const XML_Char *el, const XML
                 /* TODO */
             }
             else if (xml_strcmp(el, "luxury") == 0) {
-                /* TODO */
+                rtype->ltype = new_luxurytype(itype, 0);
             }
             else if (xml_strcmp(el, "potion") == 0) {
                 /* TODO */
@@ -291,6 +273,7 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
         switch (ud->type) {
         case EXP_RESOURCES:
             handle_resources(ud, el, attr);
+            break;
         default:
             /* not implemented */
             handle_bad_input(ud, el, NULL);
@@ -328,7 +311,7 @@ static void XMLCALL handle_data(void *data, const XML_Char *xs, int len) {
 int exparse_readfile(const char * filename) {
     XML_Parser xp;
     FILE *F;
-    int err = 1;
+    int err = 0;
     char buf[4096];
     userdata ud;
 

From ce50b888c922568ae50e453f38382fdc84a0abe3 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sat, 28 Apr 2018 18:10:04 +0200
Subject: [PATCH 09/59] finish loading luxury items.

---
 src/xmlreader.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/xmlreader.c b/src/xmlreader.c
index 111ce624e..60231688e 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -498,6 +498,10 @@ static void xml_readpotion(xmlXPathContextPtr xpath, item_type * itype)
 static luxury_type *xml_readluxury(xmlXPathContextPtr xpath, item_type * itype)
 {
     int price = xml_ivalue(xpath->node, "price", 0);
+    if (itype->rtype->ltype) {
+        itype->rtype->ltype->price = price;
+        return itype->rtype->ltype;
+    }
     return new_luxurytype(itype, price);
 }
 

From 16cebed0132954ab4af9e06b4e5f7aec8d11f934 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sat, 28 Apr 2018 18:40:14 +0200
Subject: [PATCH 10/59] implement weapons loading with expat.

---
 src/exparse.c     | 65 +++++++++++++++++++++++++++++++++++++++++++----
 src/kernel/item.c |  2 +-
 src/xmlreader.c   |  4 +--
 3 files changed, 62 insertions(+), 9 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index afaa3daf8..8a45e3fe9 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -9,6 +9,7 @@
 #include "kernel/resources.h"
 
 #include "util/log.h"
+#include "util/strings.h"
 
 #include <expat.h>
 
@@ -65,6 +66,13 @@ static int xml_int(const XML_Char *val) {
     return atoi((const char *)val);
 }
 
+static variant xml_fraction(const XML_Char *val) {
+    int num, den = 100;
+    double fval = atof((const char *)val);
+    num = (int)(fval * den + 0.5);
+    return frac_make(num, den);
+}
+
 static void handle_bad_input(userdata *ud, const XML_Char *el, const XML_Char *attr) {
     if (attr) {
         log_error("unknown attribute in <%s>: %s", (const char *)el, (const char *)attr);
@@ -168,6 +176,35 @@ static void handle_item(userdata *ud, const XML_Char *el, const XML_Char **attr)
     itype->flags = flags;
 }
 
+static void handle_weapon(userdata *ud, const XML_Char *el, const XML_Char **attr) {
+    const char *flag_names[] = { "missile", "magical", "pierce", "cut", "bash", "siege", "armorpiercing", "horse", "useshield", NULL };
+    resource_type *rtype = (resource_type *)ud->object;
+    item_type * itype = rtype->itype;
+    weapon_type *wtype = new_weapontype(itype, 0, frac_zero, NULL, 0, 0, 0, NOSKILL);
+    int i, flags = 0;
+    for (i = 0; attr[i]; i += 2) {
+        if (xml_strcmp(attr[i], "offmod") == 0) {
+            wtype->offmod = xml_int(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "defmod") == 0) {
+            wtype->defmod = xml_int(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "reload") == 0) {
+            wtype->reload = xml_int(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "skill") == 0) {
+            wtype->skill = findskill(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "magres") == 0) {
+            wtype->magres = xml_fraction(attr[i + 1]);;
+        }
+        else if (!handle_flag(&flags, attr + i, flag_names)) {
+            handle_bad_input(ud, el, attr[i]);
+        }
+    }
+    wtype->flags = flags;
+}
+
 static void XMLCALL handle_resources(userdata *ud, const XML_Char *el, const XML_Char **attr) {
     resource_type *rtype = (resource_type *)ud->object;
     if (xml_strcmp(el, "resource") == 0) {
@@ -221,12 +258,30 @@ static void XMLCALL handle_resources(userdata *ud, const XML_Char *el, const XML
                 rtype->atype = new_armortype(itype, 0.0, frac_zero, 0, 0);
             }
             else if (xml_strcmp(el, "weapon") == 0) {
-                rtype->wtype = new_weapontype(itype, 0, frac_zero, NULL, 0, 0, 0, SK_MELEE);
-                /* TODO */
+                handle_weapon(ud, el, attr);
             }
-            else if (xml_strcmp(el, "damage") == 0) {
-                assert(rtype->wtype);
-                /* TODO */
+            else if (rtype->wtype) {
+                weapon_type *wtype = rtype->wtype;
+                if (xml_strcmp(el, "damage") == 0) {
+                    int i, pos = 0;
+                    for (i = 0; attr[i]; i += 2) {
+                        if (xml_strcmp(attr[i], "type") == 0) {
+                            /* damage vs. rider(1) or not(0)? */
+                            if (xml_strcmp(attr[i + 1], "rider") == 0) {
+                                pos = 1;
+                            }
+                        }
+                        else if (xml_strcmp(attr[i], "value") == 0) {
+                            wtype->damage[pos] = str_strdup(attr[i + 1]);
+                        }
+                        else {
+                            handle_bad_input(ud, el, NULL);
+                        }
+                    }
+                }
+                else {
+                    handle_bad_input(ud, el, NULL);
+                }
             }
             else {
                 handle_bad_input(ud, el, NULL);
diff --git a/src/kernel/item.c b/src/kernel/item.c
index a573dc4ba..ef0f46768 100644
--- a/src/kernel/item.c
+++ b/src/kernel/item.c
@@ -291,7 +291,7 @@ weapon_type *new_weapontype(item_type * itype,
         wtype->damage[1] = str_strdup(damage[1]);
     }
     wtype->defmod = defmod;
-    wtype->flags |= wflags;
+    wtype->flags = wflags;
     wtype->itype = itype;
     wtype->magres = magres;
     wtype->offmod = offmod;
diff --git a/src/xmlreader.c b/src/xmlreader.c
index 60231688e..af057fc03 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -548,7 +548,7 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype)
         flags |= WTF_PIERCE;
     if (xml_bvalue(node, "cut", false))
         flags |= WTF_CUT;
-    if (xml_bvalue(node, "blunt", false))
+    if (xml_bvalue(node, "bash", false))
         flags |= WTF_BLUNT;
     if (xml_bvalue(node, "siege", false))
         flags |= WTF_SIEGE;
@@ -581,8 +581,6 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype)
 
         propValue = xmlGetProp(node, BAD_CAST "value");
         wtype->damage[pos] = str_strdup((const char *)propValue); /* TODO: this is a memory leak */
-        if (k == 0)
-            wtype->damage[1 - pos] = wtype->damage[pos];
         xmlFree(propValue);
     }
     xmlXPathFreeObject(result);

From e4a2b6cb357d2a3f97f07e0b28cf246a947c62da Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sat, 28 Apr 2018 18:47:17 +0200
Subject: [PATCH 11/59] loading armor with expat.

---
 src/exparse.c     | 33 +++++++++++++++++++++++++++++++--
 src/kernel/item.h |  2 +-
 2 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 8a45e3fe9..e42b1c81a 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -66,6 +66,10 @@ static int xml_int(const XML_Char *val) {
     return atoi((const char *)val);
 }
 
+static double xml_float(const XML_Char *val) {
+    return atof((const char *)val);
+}
+
 static variant xml_fraction(const XML_Char *val) {
     int num, den = 100;
     double fval = atof((const char *)val);
@@ -176,6 +180,32 @@ static void handle_item(userdata *ud, const XML_Char *el, const XML_Char **attr)
     itype->flags = flags;
 }
 
+static void handle_armor(userdata *ud, const XML_Char *el, const XML_Char **attr) {
+    const char *flag_names[] = { "shield", "laen", NULL };
+    resource_type *rtype = (resource_type *)ud->object;
+    item_type * itype = rtype->itype;
+    armor_type *atype = new_armortype(itype, 0.0, frac_zero, 0, 0);
+    int i, flags = 0;
+    for (i = 0; attr[i]; i += 2) {
+        if (xml_strcmp(attr[i], "penalty") == 0) {
+            atype->penalty = xml_float(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "projectile") == 0) {
+            atype->projectile = xml_float(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "ac") == 0) {
+            atype->prot = xml_int(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "magres") == 0) {
+            atype->magres = xml_fraction(attr[i + 1]);
+        }
+        else if (!handle_flag(&flags, attr + i, flag_names)) {
+            handle_bad_input(ud, el, attr[i]);
+        }
+    }
+    atype->flags = flags;
+}
+
 static void handle_weapon(userdata *ud, const XML_Char *el, const XML_Char **attr) {
     const char *flag_names[] = { "missile", "magical", "pierce", "cut", "bash", "siege", "armorpiercing", "horse", "useshield", NULL };
     resource_type *rtype = (resource_type *)ud->object;
@@ -254,8 +284,7 @@ static void XMLCALL handle_resources(userdata *ud, const XML_Char *el, const XML
                 /* TODO */
             }
             else if (xml_strcmp(el, "armor") == 0) {
-                /* TODO */
-                rtype->atype = new_armortype(itype, 0.0, frac_zero, 0, 0);
+                handle_armor(ud, el, attr);
             }
             else if (xml_strcmp(el, "weapon") == 0) {
                 handle_weapon(ud, el, attr);
diff --git a/src/kernel/item.h b/src/kernel/item.h
index 9079369e8..802c483a8 100644
--- a/src/kernel/item.h
+++ b/src/kernel/item.h
@@ -159,9 +159,9 @@ extern "C" {
         const item_type *itype;
         unsigned int flags;
         double penalty;
+        double projectile; /* chance, dass ein projektil abprallt */
         variant magres;
         int prot;
-        float projectile;           /* chance, dass ein projektil abprallt */
     } armor_type;
 
 #define WTF_NONE          0x00

From 9d3385de9788c0ac1eeab91229f88b748d318845 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sat, 28 Apr 2018 18:49:13 +0200
Subject: [PATCH 12/59] still cannot read potions, requirements, functions.

---
 src/exparse.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/exparse.c b/src/exparse.c
index e42b1c81a..aca35c8ec 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -247,6 +247,7 @@ static void XMLCALL handle_resources(userdata *ud, const XML_Char *el, const XML
         }
         else if (xml_strcmp(el, "function") == 0) {
             assert(rtype);
+            ++ud->errors;
             /* TODO */
         }
         else if (rtype->itype) {
@@ -276,12 +277,14 @@ static void XMLCALL handle_resources(userdata *ud, const XML_Char *el, const XML
             else if (xml_strcmp(el, "requirement") == 0) {
                 assert(itype->construction);
                 /* TODO */
+                ++ud->errors;
             }
             else if (xml_strcmp(el, "luxury") == 0) {
                 rtype->ltype = new_luxurytype(itype, 0);
             }
             else if (xml_strcmp(el, "potion") == 0) {
                 /* TODO */
+                ++ud->errors;
             }
             else if (xml_strcmp(el, "armor") == 0) {
                 handle_armor(ud, el, attr);

From 9dbfaea708dcdd712b9edd327690445b8fb29981 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sat, 28 Apr 2018 21:12:28 +0200
Subject: [PATCH 13/59] parse construction requirements for items.

---
 src/exparse.c | 52 ++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 43 insertions(+), 9 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index aca35c8ec..0b76aa792 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -235,7 +235,11 @@ static void handle_weapon(userdata *ud, const XML_Char *el, const XML_Char **att
     wtype->flags = flags;
 }
 
-static void XMLCALL handle_resources(userdata *ud, const XML_Char *el, const XML_Char **attr) {
+#define MAX_REQUIREMENTS 8
+static requirement reqs[MAX_REQUIREMENTS];
+static int nreqs;
+
+static void XMLCALL start_resources(userdata *ud, const XML_Char *el, const XML_Char **attr) {
     resource_type *rtype = (resource_type *)ud->object;
     if (xml_strcmp(el, "resource") == 0) {
         handle_resource(ud, el, attr);
@@ -273,11 +277,23 @@ static void XMLCALL handle_resources(userdata *ud, const XML_Char *el, const XML
                     }
                 }
                 itype->construction = con;
+                nreqs = 0;
             }
             else if (xml_strcmp(el, "requirement") == 0) {
+                requirement *req;
+                int i;
                 assert(itype->construction);
-                /* TODO */
-                ++ud->errors;
+                assert(nreqs < MAX_REQUIREMENTS);
+                req = reqs + nreqs;
+                for (i = 0; attr[i]; i += 2) {
+                    if (xml_strcmp(attr[i], "type") == 0) {
+                        req->rtype = rt_get_or_create((const char *)attr[i + 1]);
+                    }
+                    else if (xml_strcmp(attr[i], "quantity") == 0) {
+                        req->number = xml_int(attr[i + 1]);
+                    }
+                }
+                ++nreqs;
             }
             else if (xml_strcmp(el, "luxury") == 0) {
                 rtype->ltype = new_luxurytype(itype, 0);
@@ -359,7 +375,7 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
     else {
         switch (ud->type) {
         case EXP_RESOURCES:
-            handle_resources(ud, el, attr);
+            start_resources(ud, el, attr);
             break;
         default:
             /* not implemented */
@@ -369,14 +385,32 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
     ++ud->depth;
 }
 
+static void end_resources(userdata *ud, const XML_Char *el) {
+    resource_type *rtype = (resource_type *)ud->object;
+    if (xml_strcmp(el, "construction") == 0) {
+        if (nreqs > 0) {
+            construction *con = rtype->itype->construction;
+            con->materials = calloc(sizeof(requirement), nreqs + 1);
+            memcpy(con->materials, reqs, sizeof(requirement) * nreqs);
+            nreqs = 0;
+        }
+    }
+}
+
 static void XMLCALL handle_end(void *data, const XML_Char *el) {
     userdata *ud = (userdata *)data;
-    --ud->depth;
-    if (ud->cdata) {
-        free(ud->cdata);
-        ud->cdata = NULL;
-        ud->clength = 0;
+
+    if (ud->type == EXP_RESOURCES) {
+        end_resources(ud, el);
     }
+    else {
+        if (ud->cdata) {
+            free(ud->cdata);
+            ud->cdata = NULL;
+            ud->clength = 0;
+        }
+    }
+    --ud->depth;
     if (ud->depth == 0) {
         ud->type = EXP_UNKNOWN;
     }

From e86f3e7589d3f753688e87f2d4bd32b55a85c98f Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sat, 28 Apr 2018 21:46:01 +0200
Subject: [PATCH 14/59] read callback fucntions for resources and weapons.

---
 src/exparse.c     | 29 +++++++++++++++++++++++++++++
 src/kernel/item.h |  4 ++++
 src/xmlreader.c   |  4 +---
 3 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 0b76aa792..8bee331fc 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -8,6 +8,7 @@
 #include "kernel/race.h"
 #include "kernel/resources.h"
 
+#include "util/functions.h"
 #include "util/log.h"
 #include "util/strings.h"
 
@@ -250,7 +251,35 @@ static void XMLCALL start_resources(userdata *ud, const XML_Char *el, const XML_
             handle_item(ud, el, attr);
         }
         else if (xml_strcmp(el, "function") == 0) {
+            const XML_Char *name = NULL;
+            pf_generic fun = NULL;
+            int i;
+
+            for (i = 0; attr[i]; i += 2) {
+                if (xml_strcmp(attr[i], "name") == 0) {
+                    name = attr[i + 1];
+                }
+                else if (xml_strcmp(attr[i], "value") == 0) {
+                    fun = get_function((const char *)attr[i + 1]);
+                }
+                else {
+                    handle_bad_input(ud, el, attr[i]);
+                }
+            }
+
             assert(rtype);
+            if (name && fun) {
+                if (xml_strcmp(name, "change") == 0) {
+                    rtype->uchange = (rtype_uchange)fun;
+                }
+                else if (xml_strcmp(name, "name") == 0) {
+                    rtype->name = (rtype_name)fun;
+                }
+                else if (xml_strcmp(name, "attack") == 0) {
+                    assert(rtype->wtype);
+                    rtype->wtype->attack = (wtype_attack)fun;
+                }
+            }
             ++ud->errors;
             /* TODO */
         }
diff --git a/src/kernel/item.h b/src/kernel/item.h
index 802c483a8..f0ee6050b 100644
--- a/src/kernel/item.h
+++ b/src/kernel/item.h
@@ -40,6 +40,7 @@ extern "C" {
     struct gamedata;
     struct rawmaterial_type;
     struct resource_mod;
+    struct weapon_type;
 
     typedef struct item {
         struct item *next;
@@ -66,9 +67,12 @@ extern "C" {
 
     void item_done(void);
 
+    typedef bool(*wtype_attack)(const struct troop *,
+        const struct weapon_type *, int *);
     typedef int(*rtype_uchange) (struct unit * user,
         const struct resource_type * rtype, int delta);
     typedef char *(*rtype_name) (const struct resource_type * rtype, int flags);
+
     typedef struct resource_type {
         /* --- constants --- */
         char *_name;             /* wie es hei�t */
diff --git a/src/xmlreader.c b/src/xmlreader.c
index cffbb9a1e..c65a4ca9c 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -654,9 +654,7 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype)
         }
         assert(propValue != NULL);
         if (strcmp((const char *)propValue, "attack") == 0) {
-            wtype->attack =
-                (bool(*)(const struct troop *, const struct weapon_type *,
-                int *))fun;
+            wtype->attack = (wtype_attack)fun;
         }
         else {
             log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, itype->rtype->_name);

From dc891a94b4d44a002af255eebf60fa7c0e1fd4cc Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sun, 29 Apr 2018 10:32:10 +0200
Subject: [PATCH 15/59] armor and weapon are harder to read than other items.
 modifier handling for weapons seems ok, except races.

---
 src/exparse.c | 382 +++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 297 insertions(+), 85 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 8bee331fc..7ceb60728 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -3,7 +3,10 @@
 #endif
 #include "exparse.h"
 
+#include "alchemy.h"
+
 #include "kernel/build.h"
+#include "kernel/building.h"
 #include "kernel/item.h"
 #include "kernel/race.h"
 #include "kernel/resources.h"
@@ -35,22 +38,23 @@
 
 enum {
     EXP_UNKNOWN,
-
     EXP_RESOURCES,
+    EXP_WEAPON,
+    EXP_ARMOR,
     EXP_BUILDINGS,
     EXP_SHIPS,
     EXP_MESSAGES,
     EXP_STRINGS,
 };
 
-typedef struct userdata {
+typedef struct parseinfo {
     int type;
     int depth;
     int errors;
     XML_Char *cdata;
     size_t clength;
     void *object;
-} userdata;
+} parseinfo;
 
 static int xml_strcmp(const XML_Char *xs, const char *cs) {
     return strcmp(xs, cs);
@@ -64,28 +68,28 @@ static bool xml_bool(const XML_Char *val) {
 }
 
 static int xml_int(const XML_Char *val) {
-    return atoi((const char *)val);
+    return atoi(val);
 }
 
 static double xml_float(const XML_Char *val) {
-    return atof((const char *)val);
+    return atof(val);
 }
 
 static variant xml_fraction(const XML_Char *val) {
     int num, den = 100;
-    double fval = atof((const char *)val);
+    double fval = atof(val);
     num = (int)(fval * den + 0.5);
     return frac_make(num, den);
 }
 
-static void handle_bad_input(userdata *ud, const XML_Char *el, const XML_Char *attr) {
+static void handle_bad_input(parseinfo *pi, const XML_Char *el, const XML_Char *attr) {
     if (attr) {
-        log_error("unknown attribute in <%s>: %s", (const char *)el, (const char *)attr);
+        log_error("unknown attribute in <%s>: %s", el, attr);
     }
     else {
-        log_error("unexpected element <%s>", (const char *)el);
+        log_error("unexpected element <%s>", el);
     }
-    ++ud->errors;
+    ++pi->errors;
 }
 
 static bool handle_flag(int *flags, const XML_Char **pair, const char *names[]) {
@@ -104,7 +108,7 @@ static bool handle_flag(int *flags, const XML_Char **pair, const char *names[])
     return false;
 }
 
-static void handle_resource(userdata *ud, const XML_Char *el, const XML_Char **attr) {
+static void handle_resource(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     const char *flag_names[] = { "item", "limited", "pooled", NULL };
     int i;
     const char *name = NULL, *appear = NULL;
@@ -113,18 +117,18 @@ static void handle_resource(userdata *ud, const XML_Char *el, const XML_Char **a
     (void)el;
     for (i = 0; attr[i]; i += 2) {
         if (xml_strcmp(attr[i], "name") == 0) {
-            name = (const char *)attr[i + 1];
+            name = attr[i + 1];
         }
         else if (xml_strcmp(attr[i], "appearance") == 0) {
             /* TODO: appearance should be a property of item, not resource */
-            appear = (const char *)attr[i + 1];
+            appear = attr[i + 1];
             flags |= RTF_ITEM;
         }
         else if (xml_strcmp(attr[i], "material") == 0) {
             material = xml_bool(attr[i + 1]);
         }
         else if (!handle_flag(&flags, attr + i, flag_names)) {
-            handle_bad_input(ud, el, attr[i]);
+            handle_bad_input(pi, el, attr[i]);
         }
     }
     if (name) {
@@ -138,14 +142,14 @@ static void handle_resource(userdata *ud, const XML_Char *el, const XML_Char **a
         if (material) {
             rmt_create(rtype);
         }
-        ud->object = rtype;
+        pi->object = rtype;
     }
 }
 
-static void handle_item(userdata *ud, const XML_Char *el, const XML_Char **attr) {
+static void handle_item(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     const char *flag_names[] = { "herb", "cursed", "notlost", "big", "animal", "vehicle", "use", NULL };
     int i, flags = ITF_NONE;
-    resource_type *rtype = (resource_type *)ud->object;
+    resource_type *rtype = (resource_type *)pi->object;
     item_type * itype = rtype->itype;
     assert(rtype);
     if (!itype) {
@@ -175,15 +179,15 @@ static void handle_item(userdata *ud, const XML_Char *el, const XML_Char **attr)
             itype->mask_deny = rc_mask(buffer);
         }
         else if (!handle_flag(&flags, attr + i, flag_names)) {
-            handle_bad_input(ud, el, attr[i]);
+            handle_bad_input(pi, el, attr[i]);
         }
     }
     itype->flags = flags;
 }
 
-static void handle_armor(userdata *ud, const XML_Char *el, const XML_Char **attr) {
+static void handle_armor(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     const char *flag_names[] = { "shield", "laen", NULL };
-    resource_type *rtype = (resource_type *)ud->object;
+    resource_type *rtype = (resource_type *)pi->object;
     item_type * itype = rtype->itype;
     armor_type *atype = new_armortype(itype, 0.0, frac_zero, 0, 0);
     int i, flags = 0;
@@ -201,15 +205,15 @@ static void handle_armor(userdata *ud, const XML_Char *el, const XML_Char **attr
             atype->magres = xml_fraction(attr[i + 1]);
         }
         else if (!handle_flag(&flags, attr + i, flag_names)) {
-            handle_bad_input(ud, el, attr[i]);
+            handle_bad_input(pi, el, attr[i]);
         }
     }
     atype->flags = flags;
 }
 
-static void handle_weapon(userdata *ud, const XML_Char *el, const XML_Char **attr) {
+static void handle_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     const char *flag_names[] = { "missile", "magical", "pierce", "cut", "bash", "siege", "armorpiercing", "horse", "useshield", NULL };
-    resource_type *rtype = (resource_type *)ud->object;
+    resource_type *rtype = (resource_type *)pi->object;
     item_type * itype = rtype->itype;
     weapon_type *wtype = new_weapontype(itype, 0, frac_zero, NULL, 0, 0, 0, NOSKILL);
     int i, flags = 0;
@@ -230,25 +234,132 @@ static void handle_weapon(userdata *ud, const XML_Char *el, const XML_Char **att
             wtype->magres = xml_fraction(attr[i + 1]);;
         }
         else if (!handle_flag(&flags, attr + i, flag_names)) {
-            handle_bad_input(ud, el, attr[i]);
+            handle_bad_input(pi, el, attr[i]);
         }
     }
     wtype->flags = flags;
 }
 
+
+static void XMLCALL start_armor(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    resource_type *rtype = (resource_type *)pi->object;
+
+    assert(rtype && rtype->atype);
+    if (xml_strcmp(el, "modifier") == 0) {
+    }
+    handle_bad_input(pi, el, NULL);
+}
+
+#define WMOD_MAX 8
+static weapon_mod wmods[WMOD_MAX];
+static int nwmods;
+
+static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    resource_type *rtype = (resource_type *)pi->object;
+
+    assert(rtype && rtype->wtype);
+    if (xml_strcmp(el, "function") == 0) {
+        ++pi->errors;
+    }
+    else if (xml_strcmp(el, "modifier") == 0) {
+        const XML_Char *type = NULL;
+        race *rc = NULL;
+        int i, flags = 0;
+        int value = 0;
+
+        for (i = 0; attr[i]; i += 2) {
+            if (xml_strcmp(attr[i], "type") == 0) {
+                type = attr[i + 1];
+            }
+            else if (xml_strcmp(attr[i], "value") == 0) {
+                value = xml_int(attr[i + 1]);
+            }
+            else if (xml_strcmp(attr[i], "race") == 0) {
+                rc = rc_get_or_create(attr[i + 1]);
+            }
+            else if (xml_strcmp(attr[i], "offensive") == 0) {
+                if (xml_bool(attr[i + 1])) {
+                    flags |= WMF_OFFENSIVE;
+                }
+            }
+            else if (xml_strcmp(attr[i], "defensive") == 0) {
+                if (xml_bool(attr[i + 1])) {
+                    flags |= WMF_DEFENSIVE;
+                }
+            }
+            else if (xml_strcmp(attr[i], "walking") == 0) {
+                if (xml_bool(attr[i + 1])) {
+                    flags |= WMF_WALKING;
+                }
+            }
+            else if (xml_strcmp(attr[i], "riding") == 0) {
+                if (xml_bool(attr[i + 1])) {
+                    flags |= WMF_RIDING;
+                }
+            }
+            else if (xml_strcmp(attr[i], "against_riding") == 0) {
+                if (xml_bool(attr[i + 1])) {
+                    flags |= WMF_AGAINST_RIDING;
+                }
+            }
+            else if (xml_strcmp(attr[i], "against_walking") == 0) {
+                if (xml_bool(attr[i + 1])) {
+                    flags |= WMF_AGAINST_WALKING;
+                }
+            }
+            else {
+                handle_bad_input(pi, el, attr[i]);
+            }
+        }
+        if (type) {
+            weapon_mod *mod = wmods + nwmods;
+
+            assert(nwmods < WMOD_MAX);
+            ++nwmods;
+
+            /* weapon modifiers */
+            if (xml_strcmp(type, "missile_target") == 0) {
+                flags |= WMF_MISSILE_TARGET;
+            }
+            else if (xml_strcmp(type, "require") == 0) {
+                /* does require even work? */
+                flags = flags;
+            }
+            else if (xml_strcmp(type, "damage") == 0) {
+                flags |= WMF_DAMAGE;
+            }
+            else if (xml_strcmp(type, "skill") == 0) {
+                flags |= WMF_SKILL;
+            }
+            else {
+                handle_bad_input(pi, el, type);
+            }
+            mod->value = value;
+            mod->flags = flags;
+            mod->races = NULL;
+        }
+        else {
+            ++pi->errors;
+        }
+    }
+    else {
+        handle_bad_input(pi, el, NULL);
+    }
+}
+
 #define MAX_REQUIREMENTS 8
 static requirement reqs[MAX_REQUIREMENTS];
 static int nreqs;
 
-static void XMLCALL start_resources(userdata *ud, const XML_Char *el, const XML_Char **attr) {
-    resource_type *rtype = (resource_type *)ud->object;
+static void XMLCALL start_resources(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    resource_type *rtype = (resource_type *)pi->object;
     if (xml_strcmp(el, "resource") == 0) {
-        handle_resource(ud, el, attr);
+        handle_resource(pi, el, attr);
     }
     else if (rtype) {
         if (xml_strcmp(el, "item") == 0) {
             assert(rtype);
-            handle_item(ud, el, attr);
+            handle_item(pi, el, attr);
         }
         else if (xml_strcmp(el, "function") == 0) {
             const XML_Char *name = NULL;
@@ -260,10 +371,10 @@ static void XMLCALL start_resources(userdata *ud, const XML_Char *el, const XML_
                     name = attr[i + 1];
                 }
                 else if (xml_strcmp(attr[i], "value") == 0) {
-                    fun = get_function((const char *)attr[i + 1]);
+                    fun = get_function(attr[i + 1]);
                 }
                 else {
-                    handle_bad_input(ud, el, attr[i]);
+                    handle_bad_input(pi, el, attr[i]);
                 }
             }
 
@@ -280,8 +391,6 @@ static void XMLCALL start_resources(userdata *ud, const XML_Char *el, const XML_
                     rtype->wtype->attack = (wtype_attack)fun;
                 }
             }
-            ++ud->errors;
-            /* TODO */
         }
         else if (rtype->itype) {
             item_type *itype = rtype->itype;
@@ -290,7 +399,7 @@ static void XMLCALL start_resources(userdata *ud, const XML_Char *el, const XML_
                 int i;
                 for (i = 0; attr[i]; i += 2) {
                     if (xml_strcmp(attr[i], "skill") == 0) {
-                        con->skill = findskill((const char *)attr[i + 1]);
+                        con->skill = findskill(attr[i + 1]);
                     }
                     else if (xml_strcmp(attr[i], "maxsize") == 0) {
                         con->maxsize = xml_int(attr[i + 1]);
@@ -302,12 +411,50 @@ static void XMLCALL start_resources(userdata *ud, const XML_Char *el, const XML_
                         con->minskill = xml_int(attr[i + 1]);
                     }
                     else {
-                        handle_bad_input(ud, el, attr[i]);
+                        handle_bad_input(pi, el, attr[i]);
                     }
                 }
                 itype->construction = con;
                 nreqs = 0;
             }
+            else if (xml_strcmp(el, "modifier") == 0) {
+                int i;
+                double value = 0;
+                building_type * btype = NULL;
+                race *rc = NULL;
+                const XML_Char *type = NULL;
+
+                for (i = 0; attr[i]; i += 2) {
+                    if (xml_strcmp(attr[i], "type") == 0) {
+                        type = attr[i + 1];
+                    }
+                    else if (xml_strcmp(attr[i], "building") == 0) {
+                        btype = bt_get_or_create(attr[i + 1]);
+                    }
+                    else if (xml_strcmp(attr[i], "race") == 0) {
+                        rc = rc_get_or_create(attr[i + 1]);
+                    }
+                    else if (xml_strcmp(attr[i], "value") == 0) {
+                        value = xml_float(attr[i + 1]);
+                    }
+                    else {
+                        handle_bad_input(pi, el, attr[i]);
+                    }
+                }
+                /* resource modifiers */
+                if (xml_strcmp(type, "skill") == 0) {
+                    /* TODO: dupe with weapons! */
+                }
+                else if (xml_strcmp(type, "save") == 0) {
+                }
+                else if (xml_strcmp(type, "require") == 0) {
+                }
+                else if (xml_strcmp(type, "material") == 0) {
+                }
+                else {
+                    handle_bad_input(pi, el, type);
+                }
+            }
             else if (xml_strcmp(el, "requirement") == 0) {
                 requirement *req;
                 int i;
@@ -316,11 +463,14 @@ static void XMLCALL start_resources(userdata *ud, const XML_Char *el, const XML_
                 req = reqs + nreqs;
                 for (i = 0; attr[i]; i += 2) {
                     if (xml_strcmp(attr[i], "type") == 0) {
-                        req->rtype = rt_get_or_create((const char *)attr[i + 1]);
+                        req->rtype = rt_get_or_create(attr[i + 1]);
                     }
                     else if (xml_strcmp(attr[i], "quantity") == 0) {
                         req->number = xml_int(attr[i + 1]);
                     }
+                    else {
+                        handle_bad_input(pi, el, attr[i]);
+                    }
                 }
                 ++nreqs;
             }
@@ -328,14 +478,24 @@ static void XMLCALL start_resources(userdata *ud, const XML_Char *el, const XML_
                 rtype->ltype = new_luxurytype(itype, 0);
             }
             else if (xml_strcmp(el, "potion") == 0) {
-                /* TODO */
-                ++ud->errors;
+                int i, level = 0;
+                for (i = 0; attr[i]; i += 2) {
+                    if (xml_strcmp(attr[i], "level") == 0) {
+                        level = xml_int(attr[i + 1]);
+                    }
+                    else {
+                        handle_bad_input(pi, el, attr[i]);
+                    }
+                }
+                new_potiontype(itype, level);
             }
             else if (xml_strcmp(el, "armor") == 0) {
-                handle_armor(ud, el, attr);
+                pi->type = EXP_ARMOR;
+                handle_armor(pi, el, attr);
             }
             else if (xml_strcmp(el, "weapon") == 0) {
-                handle_weapon(ud, el, attr);
+                pi->type = EXP_WEAPON;
+                handle_weapon(pi, el, attr);
             }
             else if (rtype->wtype) {
                 weapon_type *wtype = rtype->wtype;
@@ -352,71 +512,114 @@ static void XMLCALL start_resources(userdata *ud, const XML_Char *el, const XML_
                             wtype->damage[pos] = str_strdup(attr[i + 1]);
                         }
                         else {
-                            handle_bad_input(ud, el, NULL);
+                            handle_bad_input(pi, el, NULL);
                         }
                     }
                 }
                 else {
-                    handle_bad_input(ud, el, NULL);
+                    handle_bad_input(pi, el, NULL);
                 }
             }
             else {
-                handle_bad_input(ud, el, NULL);
+                handle_bad_input(pi, el, NULL);
             }
         }
         else {
-            handle_bad_input(ud, el, NULL);
+            handle_bad_input(pi, el, NULL);
         }
     }
     else {
-        handle_bad_input(ud, el, NULL);
+        handle_bad_input(pi, el, NULL);
     }
 }
 
 static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char **attr) {
-    userdata *ud = (userdata *)data;
-    if (ud->depth == 0) {
-        ud->type = EXP_UNKNOWN;
+    parseinfo *pi = (parseinfo *)data;
+    if (pi->depth == 0) {
+        pi->type = EXP_UNKNOWN;
         if (xml_strcmp(el, "eressea") != 0) {
-            handle_bad_input(ud, el, NULL);
+            handle_bad_input(pi, el, NULL);
         }
     }
-    else if (ud->depth == 1) {
+    else if (pi->depth == 1) {
         if (xml_strcmp(el, "resources") == 0) {
-            ud->type = EXP_RESOURCES;
+            pi->type = EXP_RESOURCES;
         }
         else if (xml_strcmp(el, "buildings") == 0) {
-            ud->type = EXP_BUILDINGS;
+            pi->type = EXP_BUILDINGS;
         }
         else if (xml_strcmp(el, "ships") == 0) {
-            ud->type = EXP_SHIPS;
+            pi->type = EXP_SHIPS;
         }
         else if (xml_strcmp(el, "messages") == 0) {
-            ud->type = EXP_MESSAGES;
+            pi->type = EXP_MESSAGES;
         }
         else if (xml_strcmp(el, "strings") == 0) {
-            ud->type = EXP_STRINGS;
+            pi->type = EXP_STRINGS;
         }
         else {
-            handle_bad_input(ud, el, NULL);
+            handle_bad_input(pi, el, NULL);
         }
     }
     else {
-        switch (ud->type) {
+        switch (pi->type) {
         case EXP_RESOURCES:
-            start_resources(ud, el, attr);
+            start_resources(pi, el, attr);
+            break;
+        case EXP_WEAPON:
+            start_weapon(pi, el, attr);
+            break;
+        case EXP_ARMOR:
+            start_armor(pi, el, attr);
             break;
         default:
             /* not implemented */
-            handle_bad_input(ud, el, NULL);
+            handle_bad_input(pi, el, NULL);
         }
     }
-    ++ud->depth;
+    ++pi->depth;
 }
 
-static void end_resources(userdata *ud, const XML_Char *el) {
-    resource_type *rtype = (resource_type *)ud->object;
-    if (xml_strcmp(el, "construction") == 0) {
+static void end_armor(parseinfo *pi, const XML_Char *el) {
+    resource_type *rtype = (resource_type *)pi->object;
+    assert(rtype && rtype->atype);
+
+    if (xml_strcmp(el, "armor") == 0) {
+        pi->type = EXP_RESOURCES;
+    }
+    else if (xml_strcmp(el, "modifier") == 0) {
+    }
+    else {
+        handle_bad_input(pi, el, NULL);
+    }
+}
+
+static void end_weapon(parseinfo *pi, const XML_Char *el) {
+    resource_type *rtype = (resource_type *)pi->object;
+    assert(rtype && rtype->wtype);
+
+    if (xml_strcmp(el, "weapon") == 0) {
+        pi->type = EXP_RESOURCES;
+    }
+    else if (xml_strcmp(el, "modifier") == 0) {
+        if (nwmods > 0) {
+            weapon_type *wtype = rtype->wtype;
+            wtype->modifiers = calloc(sizeof(weapon_mod), nwmods + 1);
+            memcpy(wtype->modifiers, wmods, sizeof(weapon_mod) * nwmods);
+            nwmods = 0;
+        }
+    }
+    else {
+        handle_bad_input(pi, el, NULL);
+    }
+}
+
+static void end_resources(parseinfo *pi, const XML_Char *el) {
+    resource_type *rtype = (resource_type *)pi->object;
+    if (xml_strcmp(el, "resources") == 0) {
+        pi->type = EXP_UNKNOWN;
+    }
+    else if (xml_strcmp(el, "construction") == 0) {
         if (nreqs > 0) {
             construction *con = rtype->itype->construction;
             con->materials = calloc(sizeof(requirement), nreqs + 1);
@@ -427,43 +630,52 @@ static void end_resources(userdata *ud, const XML_Char *el) {
 }
 
 static void XMLCALL handle_end(void *data, const XML_Char *el) {
-    userdata *ud = (userdata *)data;
+    parseinfo *pi = (parseinfo *)data;
 
-    if (ud->type == EXP_RESOURCES) {
-        end_resources(ud, el);
-    }
-    else {
-        if (ud->cdata) {
-            free(ud->cdata);
-            ud->cdata = NULL;
-            ud->clength = 0;
+    switch (pi->type) {
+    case EXP_RESOURCES:
+        end_resources(pi, el);
+        break;
+    case EXP_ARMOR:
+        end_armor(pi, el);
+        break;
+    case EXP_WEAPON:
+        end_weapon(pi, el);
+        break;
+    default:
+        if (pi->depth == 1) {
+            pi->type = EXP_UNKNOWN;
+        }
+        if (pi->cdata) {
+            free(pi->cdata);
+            pi->cdata = NULL;
+            pi->clength = 0;
         }
     }
-    --ud->depth;
-    if (ud->depth == 0) {
-        ud->type = EXP_UNKNOWN;
+    --pi->depth;
+    if (pi->depth == 0) {
+        assert(pi->type == EXP_UNKNOWN);
     }
 }
 
 static void XMLCALL handle_data(void *data, const XML_Char *xs, int len) {
-    userdata *ud = (userdata *)data;
+    parseinfo *pi = (parseinfo *)data;
     if (len > 0) {
-        if (ud->type == EXP_MESSAGES && ud->depth == 4) {
+        if (pi->type == EXP_MESSAGES && pi->depth == 4) {
             size_t bytes = (size_t)len;
-            ud->cdata = realloc(ud->cdata, ud->clength + bytes);
-            memcpy(ud->cdata + ud->clength, xs, bytes);
-            ud->clength = ud->clength + bytes;
+            pi->cdata = realloc(pi->cdata, pi->clength + bytes);
+            memcpy(pi->cdata + pi->clength, xs, bytes);
+            pi->clength = pi->clength + bytes;
         }
     }
 }
 
-
 int exparse_readfile(const char * filename) {
     XML_Parser xp;
     FILE *F;
     int err = 0;
     char buf[4096];
-    userdata ud;
+    parseinfo pi;
 
     F = fopen(filename, "r");
     if (!F) {
@@ -472,8 +684,8 @@ int exparse_readfile(const char * filename) {
     xp = XML_ParserCreate("UTF-8");
     XML_SetElementHandler(xp, handle_start, handle_end);
     XML_SetCharacterDataHandler(xp, handle_data);
-    XML_SetUserData(xp, &ud);
-    memset(&ud, 0, sizeof(ud));
+    XML_SetUserData(xp, &pi);
+    memset(&pi, 0, sizeof(pi));
     for (;;) {
         size_t len = (int) fread(buf, 1, sizeof(buf), F);
         int done;
@@ -496,11 +708,11 @@ int exparse_readfile(const char * filename) {
             break;
         }
     }
-    assert(ud.depth == 0);
+    assert(pi.depth == 0);
     XML_ParserFree(xp);
     fclose(F);
     if (err != 0) {
         return err;
     }
-    return ud.errors;
+    return pi.errors;
 }

From 10884c825ed2c74f19168d1007f6b55f44001a70 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sun, 29 Apr 2018 16:11:35 +0200
Subject: [PATCH 16/59] fix compile, invalid use of rc_mask.

---
 src/exparse.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 7ceb60728..fba7188e1 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -170,13 +170,13 @@ static void handle_item(parseinfo *pi, const XML_Char *el, const XML_Char **attr
             size_t len = strlen(attr[i + 1]);
             assert(len < sizeof(buffer));
             memcpy(buffer, attr[i + 1], len + 1);
-            itype->mask_allow = rc_mask(buffer);
+            itype->mask_allow = rc_get_mask(buffer);
         }
         else if (xml_strcmp(attr[i], "deny") == 0) {
             size_t len = strlen(attr[i + 1]);
             assert(len < sizeof(buffer));
             memcpy(buffer, attr[i + 1], len + 1);
-            itype->mask_deny = rc_mask(buffer);
+            itype->mask_deny = rc_get_mask(buffer);
         }
         else if (!handle_flag(&flags, attr + i, flag_names)) {
             handle_bad_input(pi, el, attr[i]);
@@ -263,8 +263,7 @@ static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Ch
     }
     else if (xml_strcmp(el, "modifier") == 0) {
         const XML_Char *type = NULL;
-        race *rc = NULL;
-        int i, flags = 0;
+        int i, flags = 0, race_mask = 0;
         int value = 0;
 
         for (i = 0; attr[i]; i += 2) {
@@ -274,8 +273,10 @@ static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Ch
             else if (xml_strcmp(attr[i], "value") == 0) {
                 value = xml_int(attr[i + 1]);
             }
-            else if (xml_strcmp(attr[i], "race") == 0) {
-                rc = rc_get_or_create(attr[i + 1]);
+            else if (xml_strcmp(type, "races") == 0) {
+                char list[64];
+                strcpy(list, attr[i + 1]);
+                race_mask = rc_get_mask(list);
             }
             else if (xml_strcmp(attr[i], "offensive") == 0) {
                 if (xml_bool(attr[i + 1])) {
@@ -336,7 +337,7 @@ static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Ch
             }
             mod->value = value;
             mod->flags = flags;
-            mod->races = NULL;
+            mod->race_mask = race_mask;
         }
         else {
             ++pi->errors;

From ec9038a5ea45c2bdb04f4fd504ec14913dbc2946 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sun, 29 Apr 2018 17:27:12 +0200
Subject: [PATCH 17/59] fix copy/paste errors, remove armor element handlers.

---
 src/exparse.c | 72 +++++++++++++++++++--------------------------------
 1 file changed, 27 insertions(+), 45 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index fba7188e1..f76959e5d 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -40,7 +40,6 @@ enum {
     EXP_UNKNOWN,
     EXP_RESOURCES,
     EXP_WEAPON,
-    EXP_ARMOR,
     EXP_BUILDINGS,
     EXP_SHIPS,
     EXP_MESSAGES,
@@ -241,15 +240,6 @@ static void handle_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **at
 }
 
 
-static void XMLCALL start_armor(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
-    resource_type *rtype = (resource_type *)pi->object;
-
-    assert(rtype && rtype->atype);
-    if (xml_strcmp(el, "modifier") == 0) {
-    }
-    handle_bad_input(pi, el, NULL);
-}
-
 #define WMOD_MAX 8
 static weapon_mod wmods[WMOD_MAX];
 static int nwmods;
@@ -273,7 +263,7 @@ static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Ch
             else if (xml_strcmp(attr[i], "value") == 0) {
                 value = xml_int(attr[i + 1]);
             }
-            else if (xml_strcmp(type, "races") == 0) {
+            else if (xml_strcmp(attr[i], "races") == 0) {
                 char list[64];
                 strcpy(list, attr[i + 1]);
                 race_mask = rc_get_mask(list);
@@ -352,6 +342,10 @@ static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Ch
 static requirement reqs[MAX_REQUIREMENTS];
 static int nreqs;
 
+#define RMOD_MAX 8
+static resource_mod rmods[RMOD_MAX];
+static int nrmods;
+
 static void XMLCALL start_resources(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     resource_type *rtype = (resource_type *)pi->object;
     if (xml_strcmp(el, "resource") == 0) {
@@ -420,37 +414,41 @@ static void XMLCALL start_resources(parseinfo *pi, const XML_Char *el, const XML
             }
             else if (xml_strcmp(el, "modifier") == 0) {
                 int i;
-                double value = 0;
-                building_type * btype = NULL;
-                race *rc = NULL;
                 const XML_Char *type = NULL;
+                resource_mod * mod = rmods + nrmods;
 
+                assert(nrmods < RMOD_MAX);
+                ++nrmods;
                 for (i = 0; attr[i]; i += 2) {
                     if (xml_strcmp(attr[i], "type") == 0) {
                         type = attr[i + 1];
                     }
                     else if (xml_strcmp(attr[i], "building") == 0) {
-                        btype = bt_get_or_create(attr[i + 1]);
+                        mod->btype = bt_get_or_create(attr[i + 1]);
                     }
-                    else if (xml_strcmp(attr[i], "race") == 0) {
-                        rc = rc_get_or_create(attr[i + 1]);
+                    else if (xml_strcmp(attr[i], "races") == 0) {
+                        char list[64];
+                        strcpy(list, attr[i + 1]);
+                        mod->race_mask = rc_get_mask(list);
                     }
                     else if (xml_strcmp(attr[i], "value") == 0) {
-                        value = xml_float(attr[i + 1]);
+                        mod->value = xml_fraction(attr[i + 1]);
                     }
                     else {
                         handle_bad_input(pi, el, attr[i]);
                     }
                 }
-                /* resource modifiers */
                 if (xml_strcmp(type, "skill") == 0) {
-                    /* TODO: dupe with weapons! */
-                }
-                else if (xml_strcmp(type, "save") == 0) {
-                }
-                else if (xml_strcmp(type, "require") == 0) {
+                    mod->type = RMT_PROD_SKILL;
                 }
                 else if (xml_strcmp(type, "material") == 0) {
+                    mod->type = RMT_PROD_SAVE;
+                }
+                else if (xml_strcmp(type, "require") == 0) {
+                    mod->type = RMT_PROD_REQUIRE;
+                }
+                else if (xml_strcmp(type, "save") == 0) {
+                    mod->type = RMT_USE_SAVE;
                 }
                 else {
                     handle_bad_input(pi, el, type);
@@ -491,7 +489,6 @@ static void XMLCALL start_resources(parseinfo *pi, const XML_Char *el, const XML
                 new_potiontype(itype, level);
             }
             else if (xml_strcmp(el, "armor") == 0) {
-                pi->type = EXP_ARMOR;
                 handle_armor(pi, el, attr);
             }
             else if (xml_strcmp(el, "weapon") == 0) {
@@ -570,9 +567,6 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
         case EXP_WEAPON:
             start_weapon(pi, el, attr);
             break;
-        case EXP_ARMOR:
-            start_armor(pi, el, attr);
-            break;
         default:
             /* not implemented */
             handle_bad_input(pi, el, NULL);
@@ -581,20 +575,6 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
     ++pi->depth;
 }
 
-static void end_armor(parseinfo *pi, const XML_Char *el) {
-    resource_type *rtype = (resource_type *)pi->object;
-    assert(rtype && rtype->atype);
-
-    if (xml_strcmp(el, "armor") == 0) {
-        pi->type = EXP_RESOURCES;
-    }
-    else if (xml_strcmp(el, "modifier") == 0) {
-    }
-    else {
-        handle_bad_input(pi, el, NULL);
-    }
-}
-
 static void end_weapon(parseinfo *pi, const XML_Char *el) {
     resource_type *rtype = (resource_type *)pi->object;
     assert(rtype && rtype->wtype);
@@ -618,6 +598,11 @@ static void end_weapon(parseinfo *pi, const XML_Char *el) {
 static void end_resources(parseinfo *pi, const XML_Char *el) {
     resource_type *rtype = (resource_type *)pi->object;
     if (xml_strcmp(el, "resources") == 0) {
+        if (nrmods > 0) {
+            rtype->modifiers = calloc(sizeof(resource_mod), nrmods + 1);
+            memcpy(rtype->modifiers, rmods, sizeof(resource_mod) * nrmods);
+            nrmods = 0;
+        }
         pi->type = EXP_UNKNOWN;
     }
     else if (xml_strcmp(el, "construction") == 0) {
@@ -637,9 +622,6 @@ static void XMLCALL handle_end(void *data, const XML_Char *el) {
     case EXP_RESOURCES:
         end_resources(pi, el);
         break;
-    case EXP_ARMOR:
-        end_armor(pi, el);
-        break;
     case EXP_WEAPON:
         end_weapon(pi, el);
         break;

From 177e0159c4b9f69d6b66baf29a8357a8f781a6bf Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sun, 29 Apr 2018 18:23:23 +0200
Subject: [PATCH 18/59] init construction defaults.

---
 src/exparse.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/exparse.c b/src/exparse.c
index f76959e5d..a0daf41f8 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -392,6 +392,9 @@ static void XMLCALL start_resources(parseinfo *pi, const XML_Char *el, const XML
             if (xml_strcmp(el, "construction") == 0) {
                 construction *con = calloc(sizeof(construction), 1);
                 int i;
+                con->maxsize = -1;
+                con->minskill = -1;
+                con->reqsize = 1;
                 for (i = 0; attr[i]; i += 2) {
                     if (xml_strcmp(attr[i], "skill") == 0) {
                         con->skill = findskill(attr[i + 1]);

From 12416e8b0d616d241461fe6c840e56245e802b74 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sun, 29 Apr 2018 18:44:17 +0200
Subject: [PATCH 19/59] fix reading skill modifiers.

---
 src/exparse.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index a0daf41f8..5db7f6b29 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -417,8 +417,10 @@ static void XMLCALL start_resources(parseinfo *pi, const XML_Char *el, const XML
             }
             else if (xml_strcmp(el, "modifier") == 0) {
                 int i;
+                skill_t sk = NOSKILL;
                 const XML_Char *type = NULL;
                 resource_mod * mod = rmods + nrmods;
+                const XML_Char *value = NULL;
 
                 assert(nrmods < RMOD_MAX);
                 ++nrmods;
@@ -429,13 +431,16 @@ static void XMLCALL start_resources(parseinfo *pi, const XML_Char *el, const XML
                     else if (xml_strcmp(attr[i], "building") == 0) {
                         mod->btype = bt_get_or_create(attr[i + 1]);
                     }
+                    else if (xml_strcmp(attr[i], "skill") == 0) {
+                        sk = findskill(attr[i + 1]);
+                    }
                     else if (xml_strcmp(attr[i], "races") == 0) {
                         char list[64];
                         strcpy(list, attr[i + 1]);
                         mod->race_mask = rc_get_mask(list);
                     }
                     else if (xml_strcmp(attr[i], "value") == 0) {
-                        mod->value = xml_fraction(attr[i + 1]);
+                        value = attr[i + 1];
                     }
                     else {
                         handle_bad_input(pi, el, attr[i]);
@@ -443,15 +448,19 @@ static void XMLCALL start_resources(parseinfo *pi, const XML_Char *el, const XML
                 }
                 if (xml_strcmp(type, "skill") == 0) {
                     mod->type = RMT_PROD_SKILL;
-                }
-                else if (xml_strcmp(type, "material") == 0) {
-                    mod->type = RMT_PROD_SAVE;
+                    mod->value.sa[0] = (short)sk;
+                    mod->value.sa[1] = (short)xml_int(value);
                 }
                 else if (xml_strcmp(type, "require") == 0) {
                     mod->type = RMT_PROD_REQUIRE;
                 }
+                else if (xml_strcmp(type, "material") == 0) {
+                    mod->type = RMT_PROD_SAVE;
+                    mod->value = xml_fraction(value);
+                }
                 else if (xml_strcmp(type, "save") == 0) {
                     mod->type = RMT_USE_SAVE;
+                    mod->value = xml_fraction(value);
                 }
                 else {
                     handle_bad_input(pi, el, type);
@@ -601,12 +610,14 @@ static void end_weapon(parseinfo *pi, const XML_Char *el) {
 static void end_resources(parseinfo *pi, const XML_Char *el) {
     resource_type *rtype = (resource_type *)pi->object;
     if (xml_strcmp(el, "resources") == 0) {
+        pi->type = EXP_UNKNOWN;
+    }
+    else if (xml_strcmp(el, "resource") == 0) {
         if (nrmods > 0) {
             rtype->modifiers = calloc(sizeof(resource_mod), nrmods + 1);
             memcpy(rtype->modifiers, rmods, sizeof(resource_mod) * nrmods);
             nrmods = 0;
         }
-        pi->type = EXP_UNKNOWN;
     }
     else if (xml_strcmp(el, "construction") == 0) {
         if (nreqs > 0) {

From 2579bf71b520baf4e843645592638dd18b3401f9 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sun, 29 Apr 2018 19:33:39 +0200
Subject: [PATCH 20/59] fix test_troll_quarrying_bonus

---
 src/exparse.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/exparse.c b/src/exparse.c
index 5db7f6b29..7a337b023 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -422,6 +422,8 @@ static void XMLCALL start_resources(parseinfo *pi, const XML_Char *el, const XML
                 resource_mod * mod = rmods + nrmods;
                 const XML_Char *value = NULL;
 
+                mod->race_mask = 0;
+                mod->btype = NULL;
                 assert(nrmods < RMOD_MAX);
                 ++nrmods;
                 for (i = 0; attr[i]; i += 2) {

From a8f6f1a40c690c989a3f852e110fca4d46f17498 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sun, 29 Apr 2018 20:23:41 +0200
Subject: [PATCH 21/59] there is no require element for weapons. oops.

---
 src/exparse.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 7a337b023..c98d28d6e 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -312,10 +312,6 @@ static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Ch
             if (xml_strcmp(type, "missile_target") == 0) {
                 flags |= WMF_MISSILE_TARGET;
             }
-            else if (xml_strcmp(type, "require") == 0) {
-                /* does require even work? */
-                flags = flags;
-            }
             else if (xml_strcmp(type, "damage") == 0) {
                 flags |= WMF_DAMAGE;
             }

From e5d3d77c067094c9dc8788a199928b1d261780c7 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Tue, 1 May 2018 18:52:48 +0200
Subject: [PATCH 22/59] begin parsing buildings.

---
 src/exparse.c         | 68 +++++++++++++++++++++++++++++++++++++++++++
 src/kernel/building.c |  1 +
 src/kernel/building.h | 10 ++++---
 src/tests.c           |  1 -
 src/xmlreader.c       | 20 +++----------
 5 files changed, 79 insertions(+), 21 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index c98d28d6e..590cb446b 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -541,6 +541,70 @@ static void XMLCALL start_resources(parseinfo *pi, const XML_Char *el, const XML
     }
 }
 
+const XML_Char *attr_get(const XML_Char **attr, const char *key) {
+    int i;
+    for (i = 0; attr[i]; i += 2) {
+        if (xml_strcmp(attr[i], key) == 0) {
+            return attr[i + 1];
+        }
+    }
+    return NULL;
+}
+
+static void XMLCALL start_buildings(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    const char *flag_names[] = { "nodestroy", "nobuild", "unique", "decay", "magic", "namechange", "fort", "oneperturn", NULL };
+    if (xml_strcmp(el, "building") == 0) {
+        const XML_Char *name;
+
+        name = attr_get(attr, "name");
+        if (name) {
+            building_type *btype = bt_get_or_create(name);
+            int i, flags = BTF_DEFAULT;
+
+            for (i = 0; attr[i]; i += 2) {
+                if (xml_strcmp(attr[i], "maxsize") == 0) {
+                    btype->maxsize = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "capacity") == 0) {
+                    btype->capacity = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "maxcapacity") == 0) {
+                    btype->maxcapacity = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "magresbonus") == 0) {
+                    btype->magresbonus = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "fumblebonus") == 0) {
+                    btype->fumblebonus = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "taxes") == 0) {
+                    btype->taxes = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "auraregen") == 0) {
+                    btype->auraregen = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "magres") == 0) {
+                    /* magres is specified in percent! */
+                    btype->magres = frac_make(xml_int(attr[i + 1]), 100);
+                }
+                else if (!handle_flag(&flags, attr + i, flag_names)) {
+                    /* we already handled the name earlier */
+                    if (xml_strcmp(attr[i], "name") != 0) {
+                        handle_bad_input(pi, el, attr[i]);
+                    }
+                }
+            }
+            btype->flags = flags;
+            pi->object = btype;
+        }
+    }
+    else {
+        building_type *btype = (building_type *)pi->object;
+        assert(btype);
+        handle_bad_input(pi, el, NULL);
+    }
+}
+
 static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char **attr) {
     parseinfo *pi = (parseinfo *)data;
     if (pi->depth == 0) {
@@ -571,6 +635,9 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
     }
     else {
         switch (pi->type) {
+        case EXP_BUILDINGS:
+            start_buildings(pi, el, attr);
+            break;
         case EXP_RESOURCES:
             start_resources(pi, el, attr);
             break;
@@ -639,6 +706,7 @@ static void XMLCALL handle_end(void *data, const XML_Char *el) {
         break;
     default:
         if (pi->depth == 1) {
+            pi->object = NULL;
             pi->type = EXP_UNKNOWN;
         }
         if (pi->cdata) {
diff --git a/src/kernel/building.c b/src/kernel/building.c
index c71cbc552..f3f01905f 100644
--- a/src/kernel/building.c
+++ b/src/kernel/building.c
@@ -144,6 +144,7 @@ building_type *bt_get_or_create(const char *name)
         if (btype == NULL) {
             btype = calloc(sizeof(building_type), 1);
             btype->_name = str_strdup(name);
+            btype->flags = BTF_DEFAULT;
             btype->auraregen = 1.0;
             btype->maxsize = -1;
             btype->capacity = 1;
diff --git a/src/kernel/building.h b/src/kernel/building.h
index 915a756b7..eacf42942 100644
--- a/src/kernel/building.h
+++ b/src/kernel/building.h
@@ -48,11 +48,13 @@ extern "C" {
 #define BTF_NOBUILD        0x02 /* special, can't be built */
 #define BTF_UNIQUE         0x04 /* only one per struct region (harbour) */
 #define BTF_DECAY          0x08 /* decays when not occupied */
-#define BTF_DYNAMIC        0x10 /* dynamic type, needs bt_write */
-#define BTF_MAGIC          0x40 /* magical effect */
+#define BTF_MAGIC          0x10 /* magical effect */
+#define BTF_NAMECHANGE     0x20 /* name and description can be changed more than once */
+#define BTF_FORTIFICATION  0x40 /* building_protection, safe from monsters */
 #define BTF_ONEPERTURN     0x80 /* one one sizepoint can be added per turn */
-#define BTF_NAMECHANGE    0x100 /* name and description can be changed more than once */
-#define BTF_FORTIFICATION 0x200 /* building_protection, safe from monsters */
+#define BTF_DYNAMIC        0x100 /* dynamic type, needs bt_write */
+
+#define BTF_DEFAULT (BTF_NAMECHANGE)
 
     typedef struct building_stage {
         /* construction of this building stage: */
diff --git a/src/tests.c b/src/tests.c
index e3799c1b5..696baf447 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -338,7 +338,6 @@ building_type * test_create_buildingtype(const char * name)
 {
     construction *con;
     building_type *btype = bt_get_or_create(name);
-    btype->flags = BTF_NAMECHANGE;
     if (btype->stages) {
         con = btype->stages->construction;
     } else {
diff --git a/src/xmlreader.c b/src/xmlreader.c
index 45003e021..eea73e234 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -325,20 +325,20 @@ static int parse_buildings(xmlDocPtr doc)
 
             if (xml_bvalue(node, "nodestroy", false))
                 btype->flags |= BTF_INDESTRUCTIBLE;
-            if (xml_bvalue(node, "oneperturn", false))
-                btype->flags |= BTF_ONEPERTURN;
             if (xml_bvalue(node, "nobuild", false))
                 btype->flags |= BTF_NOBUILD;
-            if (xml_bvalue(node, "namechange", true))
-                btype->flags |= BTF_NAMECHANGE;
             if (xml_bvalue(node, "unique", false))
                 btype->flags |= BTF_UNIQUE;
             if (xml_bvalue(node, "decay", false))
                 btype->flags |= BTF_DECAY;
             if (xml_bvalue(node, "magic", false))
                 btype->flags |= BTF_MAGIC;
+            if (xml_bvalue(node, "namechange", true))
+                btype->flags |= BTF_NAMECHANGE;
             if (xml_bvalue(node, "fort", false))
                 btype->flags |= BTF_FORTIFICATION;
+            if (xml_bvalue(node, "oneperturn", false))
+                btype->flags |= BTF_ONEPERTURN;
 
             /* reading eressea/buildings/building/modifier */
             xpath->node = node;
@@ -1172,18 +1172,6 @@ static int parse_spells(xmlDocPtr doc)
                 sp->syntax = str_strdup((const char *)propValue);
                 xmlFree(propValue);
             }
-#ifdef TODO /* no longer need it, spellbooks! */
-            /* magic type */
-            propValue = xmlGetProp(node, BAD_CAST "type");
-            assert(propValue != NULL);
-            for (sp->magietyp = 0; sp->magietyp != MAXMAGIETYP; ++sp->magietyp) {
-                if (strcmp(magic_school[sp->magietyp], (const char *)propValue) == 0)
-                    break;
-            }
-            assert(sp->magietyp != MAXMAGIETYP);
-            xmlFree(propValue);
-            /* level, rank and flags */
-#endif
             sp->rank = (char)xml_ivalue(node, "rank", -1);
             if (xml_bvalue(node, "los", false))
                 sp->sptyp |= TESTCANSEE;        /* must see or have contact */

From 962b8082b7416218cca762e14c95199f00012acf Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Tue, 1 May 2018 19:05:04 +0200
Subject: [PATCH 23/59] fix test for lifepotion (tree growth was fuxxing it up)

---
 scripts/tests/e2/items.lua | 1 +
 1 file changed, 1 insertion(+)

diff --git a/scripts/tests/e2/items.lua b/scripts/tests/e2/items.lua
index e444a9c73..11bcdaed5 100644
--- a/scripts/tests/e2/items.lua
+++ b/scripts/tests/e2/items.lua
@@ -13,6 +13,7 @@ function setup()
 end
 
 function test_water_of_life()
+    eressea.settings.set("rules.grow.formula", 0) -- no tree growth
     local r = region.create(0, 0, "plain")
     r:set_flag(1, false) -- no mallorn
     local f = faction.create("human")

From d2eccd56b923041d88f2e47c6dc28b038481cc60 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Tue, 1 May 2018 19:39:41 +0200
Subject: [PATCH 24/59] defaults

---
 src/kernel/building.test.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/kernel/building.test.c b/src/kernel/building.test.c
index 94dfd1b49..daa75b496 100644
--- a/src/kernel/building.test.c
+++ b/src/kernel/building.test.c
@@ -305,7 +305,7 @@ static void test_btype_defaults(CuTest *tc) {
     CuAssertIntEquals(tc, 0, btype->magres.sa[0]);
     CuAssertIntEquals(tc, 0, btype->magresbonus);
     CuAssertIntEquals(tc, 0, btype->fumblebonus);
-    CuAssertIntEquals(tc, 0, btype->flags);
+    CuAssertIntEquals(tc, BTF_DEFAULT, btype->flags);
     test_teardown();
 }
 

From 7128e1fb5c13601ec00b4489ec2176f94d422bd0 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Tue, 1 May 2018 20:03:13 +0200
Subject: [PATCH 25/59] extract modifier parsing so it can be used for
 buildings.

---
 src/exparse.c | 136 +++++++++++++++++++++++++++++---------------------
 1 file changed, 80 insertions(+), 56 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 590cb446b..23f1f6535 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -342,7 +342,61 @@ static int nreqs;
 static resource_mod rmods[RMOD_MAX];
 static int nrmods;
 
-static void XMLCALL start_resources(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+static void handle_modifier(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    int i;
+    skill_t sk = NOSKILL;
+    const XML_Char *type = NULL;
+    resource_mod * mod = rmods + nrmods;
+    const XML_Char *value = NULL;
+
+    mod->race_mask = 0;
+    mod->btype = NULL;
+    assert(nrmods < RMOD_MAX);
+    ++nrmods;
+    for (i = 0; attr[i]; i += 2) {
+        if (xml_strcmp(attr[i], "type") == 0) {
+            type = attr[i + 1];
+        }
+        else if (xml_strcmp(attr[i], "building") == 0) {
+            mod->btype = bt_get_or_create(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "skill") == 0) {
+            sk = findskill(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "races") == 0) {
+            char list[64];
+            strcpy(list, attr[i + 1]);
+            mod->race_mask = rc_get_mask(list);
+        }
+        else if (xml_strcmp(attr[i], "value") == 0) {
+            value = attr[i + 1];
+        }
+        else {
+            handle_bad_input(pi, el, attr[i]);
+        }
+    }
+    if (xml_strcmp(type, "skill") == 0) {
+        mod->type = RMT_PROD_SKILL;
+        mod->value.sa[0] = (short)sk;
+        mod->value.sa[1] = (short)xml_int(value);
+    }
+    else if (xml_strcmp(type, "require") == 0) {
+        mod->type = RMT_PROD_REQUIRE;
+    }
+    else if (xml_strcmp(type, "material") == 0) {
+        mod->type = RMT_PROD_SAVE;
+        mod->value = xml_fraction(value);
+    }
+    else if (xml_strcmp(type, "save") == 0) {
+        mod->type = RMT_USE_SAVE;
+        mod->value = xml_fraction(value);
+    }
+    else {
+        handle_bad_input(pi, el, type);
+    }
+}
+
+static void start_resources(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     resource_type *rtype = (resource_type *)pi->object;
     if (xml_strcmp(el, "resource") == 0) {
         handle_resource(pi, el, attr);
@@ -412,57 +466,7 @@ static void XMLCALL start_resources(parseinfo *pi, const XML_Char *el, const XML
                 nreqs = 0;
             }
             else if (xml_strcmp(el, "modifier") == 0) {
-                int i;
-                skill_t sk = NOSKILL;
-                const XML_Char *type = NULL;
-                resource_mod * mod = rmods + nrmods;
-                const XML_Char *value = NULL;
-
-                mod->race_mask = 0;
-                mod->btype = NULL;
-                assert(nrmods < RMOD_MAX);
-                ++nrmods;
-                for (i = 0; attr[i]; i += 2) {
-                    if (xml_strcmp(attr[i], "type") == 0) {
-                        type = attr[i + 1];
-                    }
-                    else if (xml_strcmp(attr[i], "building") == 0) {
-                        mod->btype = bt_get_or_create(attr[i + 1]);
-                    }
-                    else if (xml_strcmp(attr[i], "skill") == 0) {
-                        sk = findskill(attr[i + 1]);
-                    }
-                    else if (xml_strcmp(attr[i], "races") == 0) {
-                        char list[64];
-                        strcpy(list, attr[i + 1]);
-                        mod->race_mask = rc_get_mask(list);
-                    }
-                    else if (xml_strcmp(attr[i], "value") == 0) {
-                        value = attr[i + 1];
-                    }
-                    else {
-                        handle_bad_input(pi, el, attr[i]);
-                    }
-                }
-                if (xml_strcmp(type, "skill") == 0) {
-                    mod->type = RMT_PROD_SKILL;
-                    mod->value.sa[0] = (short)sk;
-                    mod->value.sa[1] = (short)xml_int(value);
-                }
-                else if (xml_strcmp(type, "require") == 0) {
-                    mod->type = RMT_PROD_REQUIRE;
-                }
-                else if (xml_strcmp(type, "material") == 0) {
-                    mod->type = RMT_PROD_SAVE;
-                    mod->value = xml_fraction(value);
-                }
-                else if (xml_strcmp(type, "save") == 0) {
-                    mod->type = RMT_USE_SAVE;
-                    mod->value = xml_fraction(value);
-                }
-                else {
-                    handle_bad_input(pi, el, type);
-                }
+                handle_modifier(pi, el, attr);
             }
             else if (xml_strcmp(el, "requirement") == 0) {
                 requirement *req;
@@ -598,6 +602,9 @@ static void XMLCALL start_buildings(parseinfo *pi, const XML_Char *el, const XML
             pi->object = btype;
         }
     }
+    else if (xml_strcmp(el, "modifier") == 0) {
+        handle_modifier(pi, el, attr);
+    }
     else {
         building_type *btype = (building_type *)pi->object;
         assert(btype);
@@ -674,10 +681,7 @@ static void end_weapon(parseinfo *pi, const XML_Char *el) {
 
 static void end_resources(parseinfo *pi, const XML_Char *el) {
     resource_type *rtype = (resource_type *)pi->object;
-    if (xml_strcmp(el, "resources") == 0) {
-        pi->type = EXP_UNKNOWN;
-    }
-    else if (xml_strcmp(el, "resource") == 0) {
+    if (xml_strcmp(el, "resource") == 0) {
         if (nrmods > 0) {
             rtype->modifiers = calloc(sizeof(resource_mod), nrmods + 1);
             memcpy(rtype->modifiers, rmods, sizeof(resource_mod) * nrmods);
@@ -692,12 +696,32 @@ static void end_resources(parseinfo *pi, const XML_Char *el) {
             nreqs = 0;
         }
     }
+    else if (xml_strcmp(el, "resources") == 0) {
+        pi->type = EXP_UNKNOWN;
+    }
+}
+
+static void end_buildings(parseinfo *pi, const XML_Char *el) {
+    building_type *btype = (building_type *)pi->object;
+    if (xml_strcmp(el, "building") == 0) {
+        if (nrmods > 0) {
+            btype->modifiers = calloc(sizeof(resource_mod), nrmods + 1);
+            memcpy(btype->modifiers, rmods, sizeof(resource_mod) * nrmods);
+            nrmods = 0;
+        }
+    }
+    else if (xml_strcmp(el, "buildings") == 0) {
+        pi->type = EXP_UNKNOWN;
+    }
 }
 
 static void XMLCALL handle_end(void *data, const XML_Char *el) {
     parseinfo *pi = (parseinfo *)data;
 
     switch (pi->type) {
+    case EXP_BUILDINGS:
+        end_buildings(pi, el);
+        break;
     case EXP_RESOURCES:
         end_resources(pi, el);
         break;

From 59f74d0a98f4821e4cb2fdb0629125aab4984fd0 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Tue, 1 May 2018 20:58:30 +0200
Subject: [PATCH 26/59] parse building stages, too.

---
 src/exparse.c | 162 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 106 insertions(+), 56 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 23f1f6535..034343128 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -81,6 +81,20 @@ static variant xml_fraction(const XML_Char *val) {
     return frac_make(num, den);
 }
 
+static building_stage *stage;
+
+#define MAX_REQUIREMENTS 8
+static requirement reqs[MAX_REQUIREMENTS];
+static int nreqs;
+
+#define RMOD_MAX 8
+static resource_mod rmods[RMOD_MAX];
+static int nrmods;
+
+#define WMOD_MAX 8
+static weapon_mod wmods[WMOD_MAX];
+static int nwmods;
+
 static void handle_bad_input(parseinfo *pi, const XML_Char *el, const XML_Char *attr) {
     if (attr) {
         log_error("unknown attribute in <%s>: %s", el, attr);
@@ -239,11 +253,6 @@ static void handle_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **at
     wtype->flags = flags;
 }
 
-
-#define WMOD_MAX 8
-static weapon_mod wmods[WMOD_MAX];
-static int nwmods;
-
 static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     resource_type *rtype = (resource_type *)pi->object;
 
@@ -334,13 +343,25 @@ static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Ch
     }
 }
 
-#define MAX_REQUIREMENTS 8
-static requirement reqs[MAX_REQUIREMENTS];
-static int nreqs;
+static void handle_requirement(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    requirement *req;
+    int i;
 
-#define RMOD_MAX 8
-static resource_mod rmods[RMOD_MAX];
-static int nrmods;
+    assert(nreqs < MAX_REQUIREMENTS);
+    req = reqs + nreqs;
+    for (i = 0; attr[i]; i += 2) {
+        if (xml_strcmp(attr[i], "type") == 0) {
+            req->rtype = rt_get_or_create(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "quantity") == 0) {
+            req->number = xml_int(attr[i + 1]);
+        }
+        else {
+            handle_bad_input(pi, el, attr[i]);
+        }
+    }
+    ++nreqs;
+}
 
 static void handle_modifier(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     int i;
@@ -396,6 +417,37 @@ static void handle_modifier(parseinfo *pi, const XML_Char *el, const XML_Char **
     }
 }
 
+static construction *parse_construction(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    construction *con = calloc(sizeof(construction), 1);
+    int i;
+    con->maxsize = -1;
+    con->minskill = -1;
+    con->reqsize = 1;
+    for (i = 0; attr[i]; i += 2) {
+        if (xml_strcmp(attr[i], "skill") == 0) {
+            con->skill = findskill(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "maxsize") == 0) {
+            con->maxsize = xml_int(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "reqsize") == 0) {
+            con->reqsize = xml_int(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "minskill") == 0) {
+            con->minskill = xml_int(attr[i + 1]);
+        }
+        else if (stage != NULL && xml_strcmp(attr[i], "name") == 0) {
+            /* only building stages have names */
+            stage->name = str_strdup(attr[i + 1]);
+        }
+        else {
+            handle_bad_input(pi, el, attr[i]);
+        }
+    }
+    nreqs = 0;
+    return con;
+}
+
 static void start_resources(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     resource_type *rtype = (resource_type *)pi->object;
     if (xml_strcmp(el, "resource") == 0) {
@@ -440,52 +492,14 @@ static void start_resources(parseinfo *pi, const XML_Char *el, const XML_Char **
         else if (rtype->itype) {
             item_type *itype = rtype->itype;
             if (xml_strcmp(el, "construction") == 0) {
-                construction *con = calloc(sizeof(construction), 1);
-                int i;
-                con->maxsize = -1;
-                con->minskill = -1;
-                con->reqsize = 1;
-                for (i = 0; attr[i]; i += 2) {
-                    if (xml_strcmp(attr[i], "skill") == 0) {
-                        con->skill = findskill(attr[i + 1]);
-                    }
-                    else if (xml_strcmp(attr[i], "maxsize") == 0) {
-                        con->maxsize = xml_int(attr[i + 1]);
-                    }
-                    else if (xml_strcmp(attr[i], "reqsize") == 0) {
-                        con->reqsize = xml_int(attr[i + 1]);
-                    }
-                    else if (xml_strcmp(attr[i], "minskill") == 0) {
-                        con->minskill = xml_int(attr[i + 1]);
-                    }
-                    else {
-                        handle_bad_input(pi, el, attr[i]);
-                    }
-                }
-                itype->construction = con;
-                nreqs = 0;
+                itype->construction = parse_construction(pi, el, attr);
             }
             else if (xml_strcmp(el, "modifier") == 0) {
                 handle_modifier(pi, el, attr);
             }
             else if (xml_strcmp(el, "requirement") == 0) {
-                requirement *req;
-                int i;
                 assert(itype->construction);
-                assert(nreqs < MAX_REQUIREMENTS);
-                req = reqs + nreqs;
-                for (i = 0; attr[i]; i += 2) {
-                    if (xml_strcmp(attr[i], "type") == 0) {
-                        req->rtype = rt_get_or_create(attr[i + 1]);
-                    }
-                    else if (xml_strcmp(attr[i], "quantity") == 0) {
-                        req->number = xml_int(attr[i + 1]);
-                    }
-                    else {
-                        handle_bad_input(pi, el, attr[i]);
-                    }
-                }
-                ++nreqs;
+                handle_requirement(pi, el, attr);
             }
             else if (xml_strcmp(el, "luxury") == 0) {
                 rtype->ltype = new_luxurytype(itype, 0);
@@ -560,6 +574,7 @@ static void XMLCALL start_buildings(parseinfo *pi, const XML_Char *el, const XML
     if (xml_strcmp(el, "building") == 0) {
         const XML_Char *name;
 
+        assert(stage == NULL);
         name = attr_get(attr, "name");
         if (name) {
             building_type *btype = bt_get_or_create(name);
@@ -602,13 +617,25 @@ static void XMLCALL start_buildings(parseinfo *pi, const XML_Char *el, const XML
             pi->object = btype;
         }
     }
-    else if (xml_strcmp(el, "modifier") == 0) {
-        handle_modifier(pi, el, attr);
-    }
     else {
         building_type *btype = (building_type *)pi->object;
         assert(btype);
-        handle_bad_input(pi, el, NULL);
+        if (xml_strcmp(el, "modifier") == 0) {
+            handle_modifier(pi, el, attr);
+        }
+        else if (xml_strcmp(el, "requirement") == 0) {
+            assert(stage);
+            assert(stage->construction);
+            handle_requirement(pi, el, attr);
+        }
+        else if (xml_strcmp(el, "construction") == 0) {
+            assert(stage == NULL);
+            stage = calloc(1, sizeof(building_stage));
+            stage->construction = parse_construction(pi, el, attr);
+        }
+        else {
+            handle_bad_input(pi, el, NULL);
+        }
     }
 }
 
@@ -701,9 +728,32 @@ static void end_resources(parseinfo *pi, const XML_Char *el) {
     }
 }
 
+
 static void end_buildings(parseinfo *pi, const XML_Char *el) {
+    /* stores the end of the building's stage list: */
+    static building_stage **stage_ptr;
+
     building_type *btype = (building_type *)pi->object;
-    if (xml_strcmp(el, "building") == 0) {
+    if (xml_strcmp(el, "construction") == 0) {
+        if (stage) {
+            if (nreqs > 0) {
+                construction *con = stage->construction;
+                con->materials = calloc(sizeof(requirement), nreqs + 1);
+                memcpy(con->materials, reqs, sizeof(requirement) * nreqs);
+                nreqs = 0;
+            }
+            if (stage_ptr == NULL) {
+                /* at the first build stage, initialize stage_ptr: */
+                assert(btype->stages == NULL);
+                stage_ptr = &btype->stages;
+            }
+            *stage_ptr = stage;
+            stage_ptr = &stage->next;
+            stage = NULL;
+        }
+    }
+    else if (xml_strcmp(el, "building") == 0) {
+        stage_ptr = NULL;
         if (nrmods > 0) {
             btype->modifiers = calloc(sizeof(resource_mod), nrmods + 1);
             memcpy(btype->modifiers, rmods, sizeof(resource_mod) * nrmods);

From 6d9ecd1879dfbd9b9586d0c7f527096e6f3ec960 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Wed, 2 May 2018 21:37:57 +0200
Subject: [PATCH 27/59] finish loading buildings with expat.

---
 src/exparse.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/src/exparse.c b/src/exparse.c
index 034343128..d50db46a0 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -83,6 +83,10 @@ static variant xml_fraction(const XML_Char *val) {
 
 static building_stage *stage;
 
+#define UPKEEP_MAX 4
+static maintenance upkeep[UPKEEP_MAX];
+static int nupkeep;
+
 #define MAX_REQUIREMENTS 8
 static requirement reqs[MAX_REQUIREMENTS];
 static int nreqs;
@@ -363,6 +367,32 @@ static void handle_requirement(parseinfo *pi, const XML_Char *el, const XML_Char
     ++nreqs;
 }
 
+static void handle_maintenance(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    maintenance *up;
+    int i;
+
+    assert(nupkeep < UPKEEP_MAX);
+    up = upkeep + nupkeep;
+    memset(up, 0, sizeof(maintenance));
+    for (i = 0; attr[i]; i += 2) {
+        if (xml_strcmp(attr[i], "type") == 0) {
+            up->rtype = rt_get_or_create(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "amount") == 0) {
+            up->number = xml_int(attr[i + 1]);
+        }
+        else if (xml_strcmp(attr[i], "variable") == 0) {
+            if (xml_bool(attr[i + 1])) {
+                up->flags |= MTF_VARIABLE;
+            }
+        }
+        else {
+            handle_bad_input(pi, el, attr[i]);
+        }
+    }
+    ++nupkeep;
+}
+
 static void handle_modifier(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     int i;
     skill_t sk = NOSKILL;
@@ -633,6 +663,10 @@ static void XMLCALL start_buildings(parseinfo *pi, const XML_Char *el, const XML
             stage = calloc(1, sizeof(building_stage));
             stage->construction = parse_construction(pi, el, attr);
         }
+        else if (xml_strcmp(el, "maintenance") == 0) {
+            assert(!btype->maintenance);
+            handle_maintenance(pi, el, attr);
+        }
         else {
             handle_bad_input(pi, el, NULL);
         }
@@ -754,6 +788,11 @@ static void end_buildings(parseinfo *pi, const XML_Char *el) {
     }
     else if (xml_strcmp(el, "building") == 0) {
         stage_ptr = NULL;
+        if (nupkeep > 0) {
+            btype->maintenance = calloc(sizeof(maintenance), nupkeep + 1);
+            memcpy(btype->maintenance, upkeep, sizeof(maintenance) * nupkeep);
+            nupkeep = 0;
+        }
         if (nrmods > 0) {
             btype->modifiers = calloc(sizeof(resource_mod), nrmods + 1);
             memcpy(btype->modifiers, rmods, sizeof(resource_mod) * nrmods);

From cb27895b81cff33c52b92f689bb210c01716b417 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Thu, 3 May 2018 22:27:28 +0200
Subject: [PATCH 28/59] parsing ships, done!

---
 src/exparse.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 163 insertions(+), 6 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index d50db46a0..3e7e8b7a8 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -10,6 +10,8 @@
 #include "kernel/item.h"
 #include "kernel/race.h"
 #include "kernel/resources.h"
+#include "kernel/ship.h"
+#include "kernel/terrain.h"
 
 #include "util/functions.h"
 #include "util/log.h"
@@ -42,6 +44,7 @@ enum {
     EXP_WEAPON,
     EXP_BUILDINGS,
     EXP_SHIPS,
+    EXP_RACES,
     EXP_MESSAGES,
     EXP_STRINGS,
 };
@@ -81,6 +84,16 @@ static variant xml_fraction(const XML_Char *val) {
     return frac_make(num, den);
 }
 
+const XML_Char *attr_get(const XML_Char **attr, const char *key) {
+    int i;
+    for (i = 0; attr[i]; i += 2) {
+        if (xml_strcmp(attr[i], key) == 0) {
+            return attr[i + 1];
+        }
+    }
+    return NULL;
+}
+
 static building_stage *stage;
 
 #define UPKEEP_MAX 4
@@ -393,6 +406,20 @@ static void handle_maintenance(parseinfo *pi, const XML_Char *el, const XML_Char
     ++nupkeep;
 }
 
+#define COASTS_MAX 16
+static int ncoasts;
+static struct terrain_type *coasts[COASTS_MAX];
+
+static void handle_coast(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    const XML_Char *tname = attr_get(attr, "terrain");
+
+    if (tname) {
+        terrain_type *coast = get_or_create_terrain(tname);
+        assert(ncoasts < COASTS_MAX);
+        coasts[ncoasts++] = coast;
+    }
+}
+
 static void handle_modifier(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     int i;
     skill_t sk = NOSKILL;
@@ -589,14 +616,109 @@ static void start_resources(parseinfo *pi, const XML_Char *el, const XML_Char **
     }
 }
 
-const XML_Char *attr_get(const XML_Char **attr, const char *key) {
-    int i;
-    for (i = 0; attr[i]; i += 2) {
-        if (xml_strcmp(attr[i], key) == 0) {
-            return attr[i + 1];
+static void XMLCALL start_ships(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    const char *flag_names[] = { "opensea", "fly", "nocoast", "speedy", NULL };
+    if (xml_strcmp(el, "ship") == 0) {
+        const XML_Char *name;
+
+        name = attr_get(attr, "name");
+        if (name) {
+            ship_type *stype = st_get_or_create(name);
+            int i, flags = SFL_DEFAULT;
+
+            for (i = 0; attr[i]; i += 2) {
+                if (xml_strcmp(attr[i], "range") == 0) {
+                    stype->range = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "maxrange") == 0) {
+                    stype->range_max = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "cabins") == 0) {
+                    stype->cabins = PERSON_WEIGHT * xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "cargo") == 0) {
+                    stype->cargo = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "combat") == 0) {
+                    stype->combat = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "fishing") == 0) {
+                    stype->fishing = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "cptskill") == 0) {
+                    stype->cptskill = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "minskill") == 0) {
+                    stype->minskill = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "sumskill") == 0) {
+                    stype->sumskill = xml_int(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "damage") == 0) {
+                    stype->damage = xml_float(attr[i + 1]);
+                }
+                else if (xml_strcmp(attr[i], "storm") == 0) {
+                    stype->storm = xml_float(attr[i + 1]);
+                }
+                else if (!handle_flag(&flags, attr + i, flag_names)) {
+                    /* we already handled the name earlier */
+                    if (xml_strcmp(attr[i], "name") != 0) {
+                        handle_bad_input(pi, el, attr[i]);
+                    }
+                }
+            }
+            stype->flags = flags;
+            pi->object = stype;
+        }
+    }
+    else {
+        ship_type *stype = (ship_type *)pi->object;
+        assert(stype);
+        if (xml_strcmp(el, "modifier") == 0) {
+            /* these modifiers are not like buildings */
+            int i;
+            const XML_Char *type = NULL, *value = NULL;
+            for (i = 0; attr[i]; i += 2) {
+                if (xml_strcmp(attr[i], "type") == 0) {
+                    type = attr[i + 1];
+                }
+                else if (xml_strcmp(attr[i], "value") == 0) {
+                    value = attr[i + 1];
+                }
+                else if (xml_strcmp(attr[i], "factor") == 0) {
+                    value = attr[i + 1];
+                }
+                else {
+                    handle_bad_input(pi, el, attr[i]);
+                }
+            }
+            if (type) {
+                if (xml_strcmp(type, "tactics") == 0) {
+                    stype->tac_bonus = xml_float(value);
+                }
+                else if (xml_strcmp(type, "attack") == 0) {
+                    stype->at_bonus = xml_int(value);
+                }
+                else if (xml_strcmp(type, "defense") == 0) {
+                    stype->df_bonus = xml_int(value);
+                }
+            }
+        }
+        else if (xml_strcmp(el, "requirement") == 0) {
+            assert(stype->construction);
+            handle_requirement(pi, el, attr);
+        }
+        else if (xml_strcmp(el, "construction") == 0) {
+            assert(!stype->construction);
+            stype->construction = parse_construction(pi, el, attr);
+        }
+        else if (xml_strcmp(el, "coast") == 0) {
+            handle_coast(pi, el, attr);
+        }
+        else {
+            handle_bad_input(pi, el, NULL);
         }
     }
-    return NULL;
 }
 
 static void XMLCALL start_buildings(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
@@ -697,6 +819,9 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
         else if (xml_strcmp(el, "strings") == 0) {
             pi->type = EXP_STRINGS;
         }
+        else if (xml_strcmp(el, "races") == 0) {
+            pi->type = EXP_RACES;
+        }
         else {
             handle_bad_input(pi, el, NULL);
         }
@@ -706,6 +831,9 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
         case EXP_BUILDINGS:
             start_buildings(pi, el, attr);
             break;
+        case EXP_SHIPS:
+            start_ships(pi, el, attr);
+            break;
         case EXP_RESOURCES:
             start_resources(pi, el, attr);
             break;
@@ -762,6 +890,30 @@ static void end_resources(parseinfo *pi, const XML_Char *el) {
     }
 }
 
+static void end_ships(parseinfo *pi, const XML_Char *el) {
+    ship_type *stype = (ship_type *)pi->object;
+    if (xml_strcmp(el, "construction") == 0) {
+        assert(stype);
+        assert(stype->construction);
+        if (nreqs > 0) {
+            construction *con = stype->construction;
+            con->materials = calloc(sizeof(requirement), nreqs + 1);
+            memcpy(con->materials, reqs, sizeof(requirement) * nreqs);
+            nreqs = 0;
+        }
+    }
+    else if (xml_strcmp(el, "ship") == 0) {
+        if (ncoasts > 0) {
+            stype->coasts = calloc(sizeof(const terrain_type *), ncoasts + 1);
+            memcpy(stype->coasts, coasts, sizeof(const terrain_type *) * ncoasts);
+            ncoasts = 0;
+        }
+        pi->object = NULL;
+    }
+    else if (xml_strcmp(el, "ships") == 0) {
+        pi->type = EXP_UNKNOWN;
+    }
+}
 
 static void end_buildings(parseinfo *pi, const XML_Char *el) {
     /* stores the end of the building's stage list: */
@@ -769,6 +921,7 @@ static void end_buildings(parseinfo *pi, const XML_Char *el) {
 
     building_type *btype = (building_type *)pi->object;
     if (xml_strcmp(el, "construction") == 0) {
+        assert(btype);
         if (stage) {
             if (nreqs > 0) {
                 construction *con = stage->construction;
@@ -798,6 +951,7 @@ static void end_buildings(parseinfo *pi, const XML_Char *el) {
             memcpy(btype->modifiers, rmods, sizeof(resource_mod) * nrmods);
             nrmods = 0;
         }
+        pi->object = NULL;
     }
     else if (xml_strcmp(el, "buildings") == 0) {
         pi->type = EXP_UNKNOWN;
@@ -808,6 +962,9 @@ static void XMLCALL handle_end(void *data, const XML_Char *el) {
     parseinfo *pi = (parseinfo *)data;
 
     switch (pi->type) {
+    case EXP_SHIPS:
+        end_ships(pi, el);
+        break;
     case EXP_BUILDINGS:
         end_buildings(pi, el);
         break;

From 704148e4bd13d15183d8f58cbca83f25b55d51f0 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Thu, 3 May 2018 23:04:32 +0200
Subject: [PATCH 29/59] more object types I haven't handled yet.

---
 src/exparse.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/exparse.c b/src/exparse.c
index 3e7e8b7a8..d9cf52bf8 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -47,6 +47,8 @@ enum {
     EXP_RACES,
     EXP_MESSAGES,
     EXP_STRINGS,
+    EXP_SPELLS,
+    EXP_SPELLBOOKS,
 };
 
 typedef struct parseinfo {
@@ -819,6 +821,12 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
         else if (xml_strcmp(el, "strings") == 0) {
             pi->type = EXP_STRINGS;
         }
+        else if (xml_strcmp(el, "spells") == 0) {
+            pi->type = EXP_SPELLS;
+        }
+        else if (xml_strcmp(el, "spellbooks") == 0) {
+            pi->type = EXP_SPELLBOOKS;
+        }
         else if (xml_strcmp(el, "races") == 0) {
             pi->type = EXP_RACES;
         }

From 82ba0e62d4e2641d37579e700ebf43919a2ab7ba Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 4 May 2018 17:57:10 +0200
Subject: [PATCH 30/59] fix reading weapon damage.

---
 src/exparse.c | 51 +++++++++++++++++++++++----------------------------
 1 file changed, 23 insertions(+), 28 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index d9cf52bf8..aca7988fc 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -357,6 +357,24 @@ static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Ch
             ++pi->errors;
         }
     }
+    else if (xml_strcmp(el, "damage") == 0) {
+        weapon_type *wtype = rtype->wtype;
+        int i, pos = 0;
+        for (i = 0; attr[i]; i += 2) {
+            if (xml_strcmp(attr[i], "type") == 0) {
+                /* damage vs. rider(1) or not(0)? */
+                if (xml_strcmp(attr[i + 1], "rider") == 0) {
+                    pos = 1;
+                }
+            }
+            else if (xml_strcmp(attr[i], "value") == 0) {
+                wtype->damage[pos] = str_strdup(attr[i + 1]);
+            }
+            else {
+                handle_bad_input(pi, el, NULL);
+            }
+        }
+    }
     else {
         handle_bad_input(pi, el, NULL);
     }
@@ -582,29 +600,6 @@ static void start_resources(parseinfo *pi, const XML_Char *el, const XML_Char **
                 pi->type = EXP_WEAPON;
                 handle_weapon(pi, el, attr);
             }
-            else if (rtype->wtype) {
-                weapon_type *wtype = rtype->wtype;
-                if (xml_strcmp(el, "damage") == 0) {
-                    int i, pos = 0;
-                    for (i = 0; attr[i]; i += 2) {
-                        if (xml_strcmp(attr[i], "type") == 0) {
-                            /* damage vs. rider(1) or not(0)? */
-                            if (xml_strcmp(attr[i + 1], "rider") == 0) {
-                                pos = 1;
-                            }
-                        }
-                        else if (xml_strcmp(attr[i], "value") == 0) {
-                            wtype->damage[pos] = str_strdup(attr[i + 1]);
-                        }
-                        else {
-                            handle_bad_input(pi, el, NULL);
-                        }
-                    }
-                }
-                else {
-                    handle_bad_input(pi, el, NULL);
-                }
-            }
             else {
                 handle_bad_input(pi, el, NULL);
             }
@@ -1028,9 +1023,9 @@ int exparse_readfile(const char * filename) {
     XML_SetUserData(xp, &pi);
     memset(&pi, 0, sizeof(pi));
     for (;;) {
-        size_t len = (int) fread(buf, 1, sizeof(buf), F);
+        size_t len = (int)fread(buf, 1, sizeof(buf), F);
         int done;
-        
+
         if (ferror(F)) {
             log_error("read error in %s", filename);
             err = -2;
@@ -1039,9 +1034,9 @@ int exparse_readfile(const char * filename) {
         done = feof(F);
         if (XML_Parse(xp, buf, len, done) == XML_STATUS_ERROR) {
             log_error("parse error at line %" XML_FMT_INT_MOD " of %s: %" XML_FMT_STR,
-                    XML_GetCurrentLineNumber(xp),
-                    filename,
-                    XML_ErrorString(XML_GetErrorCode(xp)));
+                XML_GetCurrentLineNumber(xp),
+                filename,
+                XML_ErrorString(XML_GetErrorCode(xp)));
             err = -1;
             break;
         }

From 4e2171ace95932c48acff48dbf812e2e2bdf405d Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 4 May 2018 17:58:26 +0200
Subject: [PATCH 31/59] fix finding resources if xml is not processed in
 predetermined order.

---
 src/xmlreader.c | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/src/xmlreader.c b/src/xmlreader.c
index 6f7447bae..6fc87115a 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -386,7 +386,7 @@ static int parse_buildings(xmlDocPtr doc)
 
                 propValue = xmlGetProp(node, BAD_CAST "type");
                 assert(propValue != NULL);
-                mt->rtype = rt_find((const char *)propValue);
+                mt->rtype = rt_get_or_create((const char *)propValue);
                 assert(mt->rtype != NULL);
                 xmlFree(propValue);
 
@@ -1219,12 +1219,7 @@ static int parse_spells(xmlDocPtr doc)
                 xmlNodePtr node = result->nodesetval->nodeTab[k];
                 propValue = xmlGetProp(node, BAD_CAST "name");
                 assert(propValue);
-                rtype = rt_find((const char *)propValue);
-                if (!rtype) {
-                    log_error("spell %s uses unknown component %s.\n", sp->sname, (const char *)propValue);
-                    xmlFree(propValue);
-                    continue;
-                }
+                rtype = rt_get_or_create((const char *)propValue);
                 component->type = rtype;
                 xmlFree(propValue);
                 component->amount = xml_ivalue(node, "amount", 1);
@@ -1708,11 +1703,10 @@ static int parse_strings(xmlDocPtr doc)
 
 void register_xmlreader(void)
 {
-    xml_register_callback(parse_races);
     xml_register_callback(parse_resources);
-
     xml_register_callback(parse_buildings); /* requires resources */
     xml_register_callback(parse_ships);     /* requires resources, terrains */
+    xml_register_callback(parse_races);
     xml_register_callback(parse_equipment); /* requires resources */
 
     xml_register_callback(parse_spells); /* requires resources */

From 85509cdf65de22280c184855e177308ec0688b77 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 4 May 2018 18:41:59 +0200
Subject: [PATCH 32/59] fix some bugs in reading weapons.

---
 res/adamantium.xml          |  4 ++--
 res/core/resources/laen.xml |  6 +++---
 src/exparse.c               | 33 +++++++++++++++++++++++++--------
 src/xmlreader.c             |  2 ++
 4 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/res/adamantium.xml b/res/adamantium.xml
index 2e2311fcd..2bea686fe 100644
--- a/res/adamantium.xml
+++ b/res/adamantium.xml
@@ -6,8 +6,8 @@
     <item weight="200" score="200">
       <construction skill="mining" minskill="8"/>
     </item>
-      <modifier building="mine" type="skill" value="1"/>
-      <modifier type="require" building="mine"/>
+    <modifier building="mine" type="skill" value="1"/>
+    <modifier type="require" building="mine"/>
   </resource>
 
   <resource name="adamantiumaxe">
diff --git a/res/core/resources/laen.xml b/res/core/resources/laen.xml
index 1c14c2eff..95362280f 100644
--- a/res/core/resources/laen.xml
+++ b/res/core/resources/laen.xml
@@ -2,9 +2,9 @@
 <eressea>
 <resources>
 <resource name="laen" limited="yes" material="yes">
-    <item weight="200" score="100">
-        <construction skill="mining" minskill="7"/>
-    </item>
+  <item weight="200" score="100">
+    <construction skill="mining" minskill="7"/>
+  </item>
   <modifier building="mine" type="skill" value="1"/>
   <modifier type="require" building="mine"/>
 </resource>
diff --git a/src/exparse.c b/src/exparse.c
index aca7988fc..d00839283 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -277,7 +277,27 @@ static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Ch
 
     assert(rtype && rtype->wtype);
     if (xml_strcmp(el, "function") == 0) {
-        ++pi->errors;
+        const XML_Char *name = NULL, *type = NULL;
+        int i;
+
+        for (i = 0; attr[i]; i += 2) {
+            if (xml_strcmp(attr[i], "name") == 0) {
+                type = attr[i + 1];
+            }
+            else if (xml_strcmp(attr[i], "value") == 0) {
+                name = attr[i + 1];
+            }
+            else {
+                handle_bad_input(pi, el, attr[i]);
+            }
+        }
+        if (type && xml_strcmp(type, "attack") == 0) {
+            pf_generic fun = get_function(name);
+            rtype->wtype->attack = (wtype_attack)fun;
+        }
+        else {
+            handle_bad_input(pi, el, attr[i]);
+        }
     }
     else if (xml_strcmp(el, "modifier") == 0) {
         const XML_Char *type = NULL;
@@ -354,7 +374,7 @@ static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Ch
             mod->race_mask = race_mask;
         }
         else {
-            ++pi->errors;
+            handle_bad_input(pi, el, NULL);
         }
     }
     else if (xml_strcmp(el, "damage") == 0) {
@@ -566,14 +586,14 @@ static void start_resources(parseinfo *pi, const XML_Char *el, const XML_Char **
                 }
             }
         }
+        else if (xml_strcmp(el, "modifier") == 0) {
+            handle_modifier(pi, el, attr);
+        }
         else if (rtype->itype) {
             item_type *itype = rtype->itype;
             if (xml_strcmp(el, "construction") == 0) {
                 itype->construction = parse_construction(pi, el, attr);
             }
-            else if (xml_strcmp(el, "modifier") == 0) {
-                handle_modifier(pi, el, attr);
-            }
             else if (xml_strcmp(el, "requirement") == 0) {
                 assert(itype->construction);
                 handle_requirement(pi, el, attr);
@@ -866,9 +886,6 @@ static void end_weapon(parseinfo *pi, const XML_Char *el) {
             nwmods = 0;
         }
     }
-    else {
-        handle_bad_input(pi, el, NULL);
-    }
 }
 
 static void end_resources(parseinfo *pi, const XML_Char *el) {
diff --git a/src/xmlreader.c b/src/xmlreader.c
index 6fc87115a..41b8fef78 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -1703,9 +1703,11 @@ static int parse_strings(xmlDocPtr doc)
 
 void register_xmlreader(void)
 {
+#if 0
     xml_register_callback(parse_resources);
     xml_register_callback(parse_buildings); /* requires resources */
     xml_register_callback(parse_ships);     /* requires resources, terrains */
+#endif
     xml_register_callback(parse_races);
     xml_register_callback(parse_equipment); /* requires resources */
 

From ad0f83dcca26add4449264ee8da87d71835ed3e5 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 4 May 2018 18:48:14 +0200
Subject: [PATCH 33/59] some xmlreader code still required that resources get
 loaded first.

---
 src/kernel/item.c | 15 +++++++--------
 src/xmlreader.c   | 14 ++++++++------
 2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/src/kernel/item.c b/src/kernel/item.c
index 843107737..8afc6a5a9 100644
--- a/src/kernel/item.c
+++ b/src/kernel/item.c
@@ -243,17 +243,16 @@ item_type *it_find(const char *zname)
 }
 
 item_type *it_get_or_create(resource_type *rtype) {
-    item_type * itype;
     assert(rtype);
-    itype = it_find(rtype->_name);
-    if (!itype) {
+    if (!rtype->itype) {
+        item_type * itype;
         itype = (item_type *)calloc(sizeof(item_type), 1);
+        itype->rtype = rtype;
+        rtype->uchange = res_changeitem;
+        rtype->itype = itype;
+        rtype->flags |= RTF_ITEM;
     }
-    itype->rtype = rtype;
-    rtype->uchange = res_changeitem;
-    rtype->itype = itype;
-    rtype->flags |= RTF_ITEM;
-    return itype;
+    return rtype->itype;
 }
 
 static void lt_register(luxury_type * ltype)
diff --git a/src/xmlreader.c b/src/xmlreader.c
index 41b8fef78..48e0717f6 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -864,10 +864,12 @@ static void add_items(equipment * eq, xmlNodeSetPtr nsetItems)
             xmlNodePtr node = nsetItems->nodeTab[i];
             xmlChar *propValue;
             const struct item_type *itype;
+            struct resource_type *rtype;
 
             propValue = xmlGetProp(node, BAD_CAST "name");
             assert(propValue != NULL);
-            itype = it_find((const char *)propValue);
+            rtype = rt_get_or_create((const char *)propValue);
+            itype = it_get_or_create(rtype);
             xmlFree(propValue);
             if (itype != NULL) {
                 propValue = xmlGetProp(node, BAD_CAST "amount");
@@ -1705,14 +1707,14 @@ void register_xmlreader(void)
 {
 #if 0
     xml_register_callback(parse_resources);
-    xml_register_callback(parse_buildings); /* requires resources */
-    xml_register_callback(parse_ships);     /* requires resources, terrains */
+    xml_register_callback(parse_buildings);
+    xml_register_callback(parse_ships);
 #endif
     xml_register_callback(parse_races);
-    xml_register_callback(parse_equipment); /* requires resources */
+    xml_register_callback(parse_equipment);
 
-    xml_register_callback(parse_spells); /* requires resources */
-    xml_register_callback(parse_spellbooks);  /* requires spells */
+    xml_register_callback(parse_spells);
+    xml_register_callback(parse_spellbooks);
 
     xml_register_callback(parse_strings);
     xml_register_callback(parse_messages);

From 53f8b39e6e55436f61c2fdbf756201d335db0d95 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 4 May 2018 18:50:44 +0200
Subject: [PATCH 34/59] gcc and clang complain about unused function.

---
 src/xmlreader.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/xmlreader.c b/src/xmlreader.c
index 48e0717f6..347b3f6eb 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -1705,7 +1705,7 @@ static int parse_strings(xmlDocPtr doc)
 
 void register_xmlreader(void)
 {
-#if 0
+#ifdef _MSC_VER /* gcc and clang complain about unused function */
     xml_register_callback(parse_resources);
     xml_register_callback(parse_buildings);
     xml_register_callback(parse_ships);

From dca99ec79d2441ef68f580630a0f248d5e92f8c8 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 4 May 2018 18:53:35 +0200
Subject: [PATCH 35/59] negative, sir!

---
 src/xmlreader.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/xmlreader.c b/src/xmlreader.c
index 347b3f6eb..79c1ea094 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -1705,7 +1705,7 @@ static int parse_strings(xmlDocPtr doc)
 
 void register_xmlreader(void)
 {
-#ifdef _MSC_VER /* gcc and clang complain about unused function */
+#ifndef _MSC_VER /* gcc and clang complain about unused function */
     xml_register_callback(parse_resources);
     xml_register_callback(parse_buildings);
     xml_register_callback(parse_ships);

From 3e2aa5b1a87390a6ea75c53f855f4a1917f25eca Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sat, 5 May 2018 06:05:50 +0200
Subject: [PATCH 36/59] start ingesting spellbooks.

---
 src/exparse.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/src/exparse.c b/src/exparse.c
index d00839283..0e5e6e8bf 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -11,6 +11,7 @@
 #include "kernel/race.h"
 #include "kernel/resources.h"
 #include "kernel/ship.h"
+#include "kernel/spellbook.h"
 #include "kernel/terrain.h"
 
 #include "util/functions.h"
@@ -272,6 +273,42 @@ static void handle_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **at
     wtype->flags = flags;
 }
 
+static void XMLCALL start_spellbooks(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    spellbook * sb = (spellbook *)pi->object;
+    if (xml_strcmp(el, "spellbook") == 0) {
+        const XML_Char *name = attr_get(attr, "name");
+
+        if (name) {
+            pi->object = sb = get_spellbook(name);
+        }
+        else {
+            handle_bad_input(pi, el, NULL);
+        }
+    }
+    if (xml_strcmp(el, "entry") == 0) {
+        int i, level;
+        const XML_Char *name = NULL;
+
+        assert(sb);
+        for (i = 0; attr[i]; i += 2) {
+            if (xml_strcmp(attr[i], "name") == 0) {
+                name = attr[i + 1];
+            }
+            else if (xml_strcmp(attr[i], "level") == 0) {
+                level = xml_int(attr[i + 1]);
+            }
+            else {
+                handle_bad_input(pi, el, attr[i]);
+            }
+        }
+
+        handle_bad_input(pi, el, NULL);
+    }
+    else {
+        handle_bad_input(pi, el, NULL);
+    }
+}
+
 static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     resource_type *rtype = (resource_type *)pi->object;
 
@@ -863,6 +900,9 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
         case EXP_WEAPON:
             start_weapon(pi, el, attr);
             break;
+        case EXP_SPELLBOOKS:
+            start_spellbooks(pi, el, attr);
+            break;
         default:
             /* not implemented */
             handle_bad_input(pi, el, NULL);

From dc3918f4a647d49389a57a3eed8957b640246121 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sat, 5 May 2018 07:48:38 +0200
Subject: [PATCH 37/59] read spellbook (expat)

---
 src/exparse.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 0e5e6e8bf..bbb1155cc 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -285,13 +285,13 @@ static void XMLCALL start_spellbooks(parseinfo *pi, const XML_Char *el, const XM
             handle_bad_input(pi, el, NULL);
         }
     }
-    if (xml_strcmp(el, "entry") == 0) {
-        int i, level;
+    else if (xml_strcmp(el, "entry") == 0) {
+        int i, level = 0;
         const XML_Char *name = NULL;
 
         assert(sb);
         for (i = 0; attr[i]; i += 2) {
-            if (xml_strcmp(attr[i], "name") == 0) {
+            if (xml_strcmp(attr[i], "spell") == 0) {
                 name = attr[i + 1];
             }
             else if (xml_strcmp(attr[i], "level") == 0) {
@@ -301,8 +301,12 @@ static void XMLCALL start_spellbooks(parseinfo *pi, const XML_Char *el, const XM
                 handle_bad_input(pi, el, attr[i]);
             }
         }
-
-        handle_bad_input(pi, el, NULL);
+        if (name && level > 0) {
+            spellbook_addref(sb, name, level);
+        }
+        else {
+            handle_bad_input(pi, el, NULL);
+        }
     }
     else {
         handle_bad_input(pi, el, NULL);
@@ -876,8 +880,9 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
         else if (xml_strcmp(el, "spells") == 0) {
             pi->type = EXP_SPELLS;
         }
-        else if (xml_strcmp(el, "spellbooks") == 0) {
+        else if (xml_strcmp(el, "spellbook") == 0) {
             pi->type = EXP_SPELLBOOKS;
+            start_spellbooks(pi, el, attr);
         }
         else if (xml_strcmp(el, "races") == 0) {
             pi->type = EXP_RACES;

From a44085de7a25f5a19ac0d7aea2b471ba834b00b2 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sun, 6 May 2018 13:57:28 +0200
Subject: [PATCH 38/59] spell flags, rearranged

---
 src/exparse.c   | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/magic.h     | 36 ++++++++++++++++++------------------
 src/xmlreader.c |  4 ++--
 3 files changed, 68 insertions(+), 20 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index bbb1155cc..702c80557 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -273,6 +273,51 @@ static void handle_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **at
     wtype->flags = flags;
 }
 
+static void XMLCALL start_spells(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    const char *flag_names[] = {
+        "far", "variable", "ocean", "ship", "los", 
+        "unittarget", "shiptarget", "buildingtarget", "regiontarget", NULL };
+    if (xml_strcmp(el, "spell") == 0) {
+        spell *sp;
+        const XML_Char *name = NULL, *syntax = NULL, *parameter = NULL;
+        int i, rank = 0, flags = 0;
+        for (i = 0; attr[i]; i += 2) {
+            const XML_Char *key = attr[i], *val = attr[i + 1];
+            if (xml_strcmp(key, "name") == 0) {
+                name = val;
+            }
+            else if (xml_strcmp(key, "syntax") == 0) {
+                syntax = val;
+            }
+            else if (xml_strcmp(key, "parameters") == 0) {
+                parameter = val;
+            }
+            else if (xml_strcmp(key, "rank") == 0) {
+                rank = xml_int(val);
+            }
+            else if (xml_strcmp(key, "combat") == 0) {
+                int mode = PRECOMBATSPELL;
+                int k = xml_int(val);
+                if (k > 1 && k <= 3) {
+                   mode = mode << (k - 1);
+                }
+                flags |= mode;
+            }
+            else if (!handle_flag(&flags, attr + i, flag_names)) {
+                handle_bad_input(pi, el, attr[i]);
+            }
+        }
+        pi->object = sp = create_spell(name);
+        sp->rank = rank;
+        sp->syntax = str_strdup(syntax);
+        sp->parameter = str_strdup(parameter);
+        sp->sptyp = flags;
+    }
+    else {
+        handle_bad_input(pi, el, NULL);
+    }
+}
+
 static void XMLCALL start_spellbooks(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     spellbook * sb = (spellbook *)pi->object;
     if (xml_strcmp(el, "spellbook") == 0) {
@@ -908,6 +953,9 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
         case EXP_SPELLBOOKS:
             start_spellbooks(pi, el, attr);
             break;
+        case EXP_SPELLS:
+            start_spells(pi, el, attr);
+            break;
         default:
             /* not implemented */
             handle_bad_input(pi, el, NULL);
diff --git a/src/magic.h b/src/magic.h
index 4a00a7b13..fd87428ae 100644
--- a/src/magic.h
+++ b/src/magic.h
@@ -154,28 +154,28 @@ extern "C" {
 #define FARCASTING      (1<<0)  /* ZAUBER [struct region x y] */
 #define SPELLLEVEL      (1<<1)  /* ZAUBER [STUFE x] */
 
-    /* ID's k�nnen zu drei unterschiedlichen Entit�ten geh�ren: Einheiten,
-     * Geb�uden und Schiffen. */
-#define UNITSPELL       (1<<2)  /* ZAUBER .. <Einheit-Nr> [<Einheit-Nr> ..] */
-#define SHIPSPELL       (1<<3)  /* ZAUBER .. <Schiff-Nr> [<Schiff-Nr> ..] */
-#define BUILDINGSPELL   (1<<4)  /* ZAUBER .. <Gebaeude-Nr> [<Gebaeude-Nr> ..] */
-#define REGIONSPELL     (1<<5)  /* wirkt auf struct region */
+#define OCEANCASTABLE   (1<<2) /* K�nnen auch nicht-Meermenschen auf
+     hoher See zaubern */
+#define ONSHIPCAST      (1<<3) /* kann auch auf von Land ablegenden
+     Schiffen stehend gezaubert werden */
+#define TESTCANSEE      (1<<4) /* alle Zielunits auf cansee pr�fen */
 
-#define PRECOMBATSPELL	(1<<7)  /* PR�KAMPFZAUBER .. */
-#define COMBATSPELL     (1<<8)  /* KAMPFZAUBER .. */
-#define POSTCOMBATSPELL	(1<<9)  /* POSTKAMPFZAUBER .. */
+     /* ID's k�nnen zu drei unterschiedlichen Entit�ten geh�ren: Einheiten,
+     * Geb�uden und Schiffen. */
+#define UNITSPELL       (1<<5)  /* ZAUBER .. <Einheit-Nr> [<Einheit-Nr> ..] */
+#define SHIPSPELL       (1<<6)  /* ZAUBER .. <Schiff-Nr> [<Schiff-Nr> ..] */
+#define BUILDINGSPELL   (1<<7)  /* ZAUBER .. <Gebaeude-Nr> [<Gebaeude-Nr> ..] */
+#define REGIONSPELL     (1<<8)  /* wirkt auf struct region */
+
+#define PRECOMBATSPELL	(1<<9)  /* PR�KAMPFZAUBER .. */
+#define COMBATSPELL     (1<<10)  /* KAMPFZAUBER .. */
+#define POSTCOMBATSPELL	(1<<11)  /* POSTKAMPFZAUBER .. */
 #define ISCOMBATSPELL   (PRECOMBATSPELL|COMBATSPELL|POSTCOMBATSPELL)
 
-#define OCEANCASTABLE   (1<<10) /* K�nnen auch nicht-Meermenschen auf
-     hoher See zaubern */
-#define ONSHIPCAST      (1<<11) /* kann auch auf von Land ablegenden
-     Schiffen stehend gezaubert werden */
-    /*  */
-#define NOTFAMILIARCAST (1<<12)
-#define TESTRESISTANCE  (1<<13) /* alle Zielobjekte (u, s, b, r) auf
+#define TESTRESISTANCE  (1<<12) /* alle Zielobjekte (u, s, b, r) auf
                                        Magieresistenz pr�fen */
-#define SEARCHLOCAL     (1<<14) /* Ziel muss in der target_region sein */
-#define TESTCANSEE      (1<<15) /* alle Zielunits auf cansee pr�fen */
+#define SEARCHLOCAL     (1<<13) /* Ziel muss in der target_region sein */
+#define NOTFAMILIARCAST (1<<14) /* not used by XML? */
 #define ANYTARGET       (UNITSPELL|REGIONSPELL|BUILDINGSPELL|SHIPSPELL) /* wirkt auf alle objekttypen (unit, ship, building, region) */
 
     /* Flag Spruchkostenberechnung: */
diff --git a/src/xmlreader.c b/src/xmlreader.c
index 006c37a8a..9d910f6fe 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -1174,7 +1174,7 @@ static int parse_spells(xmlDocPtr doc)
                 sp->syntax = str_strdup((const char *)propValue);
                 xmlFree(propValue);
             }
-            sp->rank = (char)xml_ivalue(node, "rank", 0);
+            sp->rank = (char)xml_ivalue(node, "rank", sp->rank);
             if (xml_bvalue(node, "los", false))
                 sp->sptyp |= TESTCANSEE;        /* must see or have contact */
             if (!xml_bvalue(node, "target_global", false))
@@ -1705,12 +1705,12 @@ void register_xmlreader(void)
     xml_register_callback(parse_resources);
     xml_register_callback(parse_buildings);
     xml_register_callback(parse_ships);
+    xml_register_callback(parse_spellbooks);
 #endif
     xml_register_callback(parse_races);
     xml_register_callback(parse_equipment);
 
     xml_register_callback(parse_spells);
-    xml_register_callback(parse_spellbooks);
 
     xml_register_callback(parse_strings);
     xml_register_callback(parse_messages);

From adbf1098b91d3d885c6ae35d0e283ee336d98333 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Sun, 6 May 2018 14:02:44 +0200
Subject: [PATCH 39/59] we fail tests when not reading spell components.

---
 src/exparse.c   | 8 +++++++-
 src/xmlreader.c | 2 +-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 702c80557..411741c05 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -277,7 +277,13 @@ static void XMLCALL start_spells(parseinfo *pi, const XML_Char *el, const XML_Ch
     const char *flag_names[] = {
         "far", "variable", "ocean", "ship", "los", 
         "unittarget", "shiptarget", "buildingtarget", "regiontarget", NULL };
-    if (xml_strcmp(el, "spell") == 0) {
+
+    if (xml_strcmp(el, "resource") == 0) {
+        spell_component *spc = NULL;
+        (void)spc;
+        handle_bad_input(pi, el, NULL);
+    }
+    else if (xml_strcmp(el, "spell") == 0) {
         spell *sp;
         const XML_Char *name = NULL, *syntax = NULL, *parameter = NULL;
         int i, rank = 0, flags = 0;
diff --git a/src/xmlreader.c b/src/xmlreader.c
index 9d910f6fe..afb639f1a 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -1706,11 +1706,11 @@ void register_xmlreader(void)
     xml_register_callback(parse_buildings);
     xml_register_callback(parse_ships);
     xml_register_callback(parse_spellbooks);
+    xml_register_callback(parse_spells);
 #endif
     xml_register_callback(parse_races);
     xml_register_callback(parse_equipment);
 
-    xml_register_callback(parse_spells);
 
     xml_register_callback(parse_strings);
     xml_register_callback(parse_messages);

From b197bb395d48b5d5223006c9c4e59d31f5b0aeae Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Tue, 8 May 2018 23:06:33 +0200
Subject: [PATCH 40/59] parse spell components.

---
 src/exparse.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++----
 src/magic.h   | 12 ++++-----
 2 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 411741c05..bc7218383 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -273,15 +273,50 @@ static void handle_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **at
     wtype->flags = flags;
 }
 
+#define MAX_COMPONENTS 8
+static spell_component components[MAX_COMPONENTS];
+static int ncomponents;
+
 static void XMLCALL start_spells(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     const char *flag_names[] = {
         "far", "variable", "ocean", "ship", "los", 
-        "unittarget", "shiptarget", "buildingtarget", "regiontarget", NULL };
+        "unittarget", "shiptarget", "buildingtarget", "regiontarget", "globaltarget", NULL };
 
     if (xml_strcmp(el, "resource") == 0) {
-        spell_component *spc = NULL;
-        (void)spc;
-        handle_bad_input(pi, el, NULL);
+        spell_component *spc;
+        int i;
+
+        assert(ncomponents < MAX_COMPONENTS);
+        spc = components + ncomponents;
+        spc->cost = SPC_FIX;
+        ++ncomponents;
+        memset(spc, 0, sizeof(spell_component));
+        for (i = 0; attr[i]; i += 2) {
+            const XML_Char *key = attr[i], *val = attr[i + 1];
+            if (xml_strcmp(key, "name") == 0) {
+                spc->type = rt_get_or_create(val);
+            }
+            else if (xml_strcmp(key, "amount") == 0) {
+                spc->amount = xml_int(val);
+            }
+            else if (xml_strcmp(key, "cost") == 0) {
+                if (xml_strcmp(val, "level") == 0) {
+                    spc->cost = SPC_LEVEL;
+                }
+                else if (xml_strcmp(val, "linear") == 0) {
+                    spc->cost = SPC_LINEAR;
+                }
+                else if (xml_strcmp(val, "fixed") == 0) {
+                    spc->cost = SPC_FIX;
+                }
+                else {
+                    handle_bad_input(pi, key, val);
+                }
+            }
+            else {
+                handle_bad_input(pi, el, key);
+            }
+        }
     }
     else if (xml_strcmp(el, "spell") == 0) {
         spell *sp;
@@ -962,14 +997,33 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
         case EXP_SPELLS:
             start_spells(pi, el, attr);
             break;
+        case EXP_UNKNOWN:
+            handle_bad_input(pi, el, NULL);
+            break;
         default:
             /* not implemented */
             handle_bad_input(pi, el, NULL);
+            return;
         }
     }
     ++pi->depth;
 }
 
+static void end_spells(parseinfo *pi, const XML_Char *el) {
+    if (xml_strcmp(el, "spells") == 0) {
+        pi->type = EXP_UNKNOWN;
+    }
+    else if (xml_strcmp(el, "spell") == 0) {
+        spell *sp = (spell *)pi->object;
+        if (ncomponents > 0) {
+            sp->components = calloc(sizeof(spell_component), ncomponents + 1);
+            memcpy(sp->components, components, sizeof(spell_component) * ncomponents);
+            ncomponents = 0;
+        }
+        pi->object = NULL;
+    }
+}
+
 static void end_weapon(parseinfo *pi, const XML_Char *el) {
     resource_type *rtype = (resource_type *)pi->object;
     assert(rtype && rtype->wtype);
@@ -1093,6 +1147,9 @@ static void XMLCALL handle_end(void *data, const XML_Char *el) {
     case EXP_WEAPON:
         end_weapon(pi, el);
         break;
+    case EXP_SPELLS:
+        end_spells(pi, el);
+        break;
     default:
         if (pi->depth == 1) {
             pi->object = NULL;
@@ -1160,7 +1217,9 @@ int exparse_readfile(const char * filename) {
             break;
         }
     }
-    assert(pi.depth == 0);
+    if (pi.depth != 0) {
+        err = -3;
+    }
     XML_ParserFree(xp);
     fclose(F);
     if (err != 0) {
diff --git a/src/magic.h b/src/magic.h
index b76bcfa75..654673245 100644
--- a/src/magic.h
+++ b/src/magic.h
@@ -166,15 +166,15 @@ extern "C" {
 #define SHIPSPELL       (1<<6)  /* ZAUBER .. <Schiff-Nr> [<Schiff-Nr> ..] */
 #define BUILDINGSPELL   (1<<7)  /* ZAUBER .. <Gebaeude-Nr> [<Gebaeude-Nr> ..] */
 #define REGIONSPELL     (1<<8)  /* wirkt auf struct region */
+#define GLOBALTARGET    (1<<9) /* Ziel kann ausserhalb der region sein */
 
-#define PRECOMBATSPELL	(1<<9)  /* PR�KAMPFZAUBER .. */
-#define COMBATSPELL     (1<<10)  /* KAMPFZAUBER .. */
-#define POSTCOMBATSPELL	(1<<11)  /* POSTKAMPFZAUBER .. */
+#define PRECOMBATSPELL	(1<<10)  /* PR�KAMPFZAUBER .. */
+#define COMBATSPELL     (1<<11)  /* KAMPFZAUBER .. */
+#define POSTCOMBATSPELL	(1<<12)  /* POSTKAMPFZAUBER .. */
 #define ISCOMBATSPELL   (PRECOMBATSPELL|COMBATSPELL|POSTCOMBATSPELL)
 
-#define TESTRESISTANCE  (1<<12) /* alle Zielobjekte (u, s, b, r) auf
-                                       Magieresistenz pr�fen */
-#define GLOBALTARGET    (1<<13) /* Ziel muss in der target_region sein */
+
+#define TESTRESISTANCE  (1<<13) /* Zielobjekte auf Magieresistenz pr�fen. not used in XML? */
 #define NOTFAMILIARCAST (1<<14) /* not used by XML? */
 #define ANYTARGET       (UNITSPELL|REGIONSPELL|BUILDINGSPELL|SHIPSPELL) /* wirkt auf alle objekttypen (unit, ship, building, region) */
 

From 9e6ae0edc139c2c8a741c7127f4abf8ef2008985 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Wed, 9 May 2018 07:14:56 +0200
Subject: [PATCH 41/59] make str_strdup more forgiving

---
 src/util/strings.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/util/strings.c b/src/util/strings.c
index 81fdc3713..ab85328ab 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -218,6 +218,7 @@ unsigned int wang_hash(unsigned int a)
 }
 
 char *str_strdup(const char *s) {
+    if (s == NULL) return NULL;
 #ifdef HAVE_STRDUP
     return strdup(s);
 #elif defined(_MSC_VER)

From c05a65b881587ff66ef268997fa5351bc9c0b527 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Wed, 9 May 2018 22:16:30 +0200
Subject: [PATCH 42/59] expat parses (most of) races. fix canteach flag in XML.

---
 res/e3a/races.xml      |  76 ++++++++--------
 res/eressea.dtd        | 190 +++++++++++++++++++++++++++++++++++++++
 res/eressea/races.xml  |  95 ++++++++++----------
 res/races/dragon.xml   |   2 +-
 res/races/goblin-3.xml |   2 +-
 res/races/halfling.xml |   2 +-
 src/exparse.c          | 196 ++++++++++++++++++++++++++++++++++++++++-
 src/kernel/race.c      |  15 ++--
 src/kernel/race.h      |  11 ++-
 src/kernel/race.test.c |   4 +-
 src/xmlreader.c        |  22 ++---
 11 files changed, 498 insertions(+), 117 deletions(-)
 create mode 100644 res/eressea.dtd

diff --git a/res/e3a/races.xml b/res/e3a/races.xml
index bb70fa3df..00d34e58a 100644
--- a/res/e3a/races.xml
+++ b/res/e3a/races.xml
@@ -8,7 +8,7 @@
     <ai splitsize="10000" moverandom="yes" learn="yes"/>
     <attack type="1" damage="1d4"/>
   </race>
-  <race name="lynx" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="20" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="5" walk="yes" teach="no" getitem="yes">
+  <race name="lynx" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="20" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="5" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="99999"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -192,7 +192,7 @@
 
   <!-- end player races -->
 
-  <race name="kraken" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="300" damage="2d10" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" coastal="yes" swim="yes" teach="no" getitem="yes">
+  <race name="kraken" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="300" damage="2d10" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" coastal="yes" swim="yes" canteach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -218,7 +218,7 @@
     <attack type="4" damage="1d10"/>
     <attack type="4" damage="1d10"/>
   </race>
-  <race name="giantturtle" maxaura="0.000000" regaura="0.000000" weight="1600" capacity="600" speed="1.0" hp="900" ac="7" damage="2d50" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="5" coastal="yes" swim="yes" walk="yes" teach="no" getitem="yes">
+  <race name="giantturtle" maxaura="0.000000" regaura="0.000000" weight="1600" capacity="600" speed="1.0" hp="900" ac="7" damage="2d50" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="5" coastal="yes" swim="yes" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -239,7 +239,7 @@
     <skill name="cartmaking" modifier="-99"/>
     <attack type="4" damage="2d50"/>
   </race>
-  <race name="dolphin" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="24" damage="1d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="5" coastal="yes" swim="yes" teach="no" getitem="yes">
+  <race name="dolphin" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="24" damage="1d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="5" coastal="yes" swim="yes" canteach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -260,7 +260,7 @@
     <skill name="cartmaking" modifier="-99"/>
     <attack type="4" damage="1d6"/>
   </race>
-  <race name="tiger" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="30" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" walk="yes" teach="no" getitem="yes">
+  <race name="tiger" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="30" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -283,7 +283,7 @@
     <attack type="4" damage="1d6"/>
     <attack type="4" damage="1d6"/>
   </race>
-  <race name="hellcat" magres="50" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="40" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" teach="no" getitem="yes" resistpierce="yes">
+  <race name="hellcat" magres="50" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="40" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" canteach="no" getitem="yes" resistpierce="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -306,7 +306,7 @@
     <attack type="4" damage="1d6"/>
     <attack type="4" damage="1d6"/>
   </race>
-  <race name="owl" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="9" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="2" defensemodifier="4" fly="yes" walk="yes" teach="no" getitem="yes">
+  <race name="owl" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="9" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="2" defensemodifier="4" fly="yes" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -328,7 +328,7 @@
     <skill name="cartmaking" modifier="-99"/>
     <attack type="4" damage="1d4"/>
   </race>
-  <race name="fairy" magres="80" maxaura="1.0" regaura="1.500000" weight="200" capacity="540" speed="1.0" hp="6" damage="1d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="14" fly="yes" walk="yes" teach="no" getitem="yes" equipment="yes">
+  <race name="fairy" magres="80" maxaura="1.0" regaura="1.500000" weight="200" capacity="540" speed="1.0" hp="6" damage="1d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="14" fly="yes" walk="yes" canteach="no" getitem="yes" equipment="yes">
     <ai splitsize="5000"/>
     <skill name="magic" modifier="1"/>
     <skill name="riding" modifier="-1"/>
@@ -354,7 +354,7 @@
     <attack type="4" damage="1d3"/>
     <attack type="4" damage="1d3"/>
   </race>
-  <race name="dreamcat" magres="50" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="10" damage="1d5" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="6" fly="yes" walk="yes" teach="no" getitem="yes" invinciblenonmagic="yes">
+  <race name="dreamcat" magres="50" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="10" damage="1d5" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="6" fly="yes" walk="yes" canteach="no" getitem="yes" invinciblenonmagic="yes">
     <ai splitsize="5000"/>
     <skill name="magic" modifier="1"/>
     <skill name="crossbow" modifier="-99"/>
@@ -376,7 +376,7 @@
     <attack type="4" damage="1d5"/>
     <attack type="4" damage="1d5"/>
   </race>
-  <race name="imp" magres="50" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="10" ac="1" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="4" fly="yes" walk="yes" teach="no" getitem="yes" equipment="yes">
+  <race name="imp" magres="50" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="10" ac="1" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="4" fly="yes" walk="yes" canteach="no" getitem="yes" equipment="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -400,7 +400,7 @@
     <attack type="1" damage="1d4"/>
     <attack type="6" spell="fiery_dragonbreath" level="3" />
   </race>
-  <race name="ghost" magres="80" maxaura="0.500000" regaura="0.100000" weight="500" capacity="540" speed="1.0" hp="30" ac="5" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="8" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" equipment="yes" invinciblenonmagic="yes">
+  <race name="ghost" magres="80" maxaura="0.500000" regaura="0.100000" weight="500" capacity="540" speed="1.0" hp="30" ac="5" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="8" scarepeasants="yes" fly="yes" walk="yes" canteach="no" getitem="yes" equipment="yes" invinciblenonmagic="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -425,7 +425,7 @@
     <attack type="2" damage="2d30"/>
     <attack type="3" damage="1d1"/>
   </race>
-  <race name="wolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="25" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" scarepeasants="yes" walk="yes" teach="no" getitem="yes">
+  <race name="wolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="25" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" scarepeasants="yes" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -448,7 +448,7 @@
     <attack type="4" damage="1d4"/>
     <attack type="4" damage="1d4"/>
   </race>
-  <race name="unicorn" magres="90" maxaura="1.500000" regaura="1.500000" weight="5000" capacity="2000" speed="2.000000" hp="40" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" teach="no" getitem="yes">
+  <race name="unicorn" magres="90" maxaura="1.500000" regaura="1.500000" weight="5000" capacity="2000" speed="2.000000" hp="40" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -471,7 +471,7 @@
     <attack type="4" damage="3d12"/>
     <attack type="4" damage="2d4"/>
   </race>
-  <race name="nymph" magres="90" maxaura="1.0" regaura="1.500000" weight="1000" capacity="540" speed="1.0" hp="15" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" teach="no" getitem="yes" equipment="yes">
+  <race name="nymph" magres="90" maxaura="1.0" regaura="1.500000" weight="1000" capacity="540" speed="1.0" hp="15" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" canteach="no" getitem="yes" equipment="yes">
     <ai splitsize="9999"/>
     <skill name="mining" modifier="-99"/>
     <skill name="bow" modifier="2"/>
@@ -493,7 +493,7 @@
     <attack type="1" damage="1d4"/>
     <attack type="2" damage="2d20"/>
   </race>
-  <race name="songdragon" magres="99" maxaura="1.0" regaura="1.0" weight="1000" capacity="600" speed="1.500000" hp="40" ac="1" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" fly="yes" walk="yes" teach="no" getitem="yes">
+  <race name="songdragon" magres="99" maxaura="1.0" regaura="1.0" weight="1000" capacity="600" speed="1.500000" hp="40" ac="1" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" fly="yes" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -520,7 +520,7 @@
     <attack type="6" spell="fiery_dragonbreath" level="3" />
   </race>
 
-  <race name="rat" maxaura="0.000000" regaura="0.000000" weight="100" capacity="540" speed="1.0" hp="10" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" walk="yes" teach="no" getitem="yes">
+  <race name="rat" maxaura="0.000000" regaura="0.000000" weight="100" capacity="540" speed="1.0" hp="10" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -543,7 +543,7 @@
     <attack type="4" damage="1d4"/>
     <attack type="4" damage="1d4"/>
   </race>
-  <race name="eagle" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.500000" hp="15" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="2" fly="yes" walk="yes" teach="no" getitem="yes">
+  <race name="eagle" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.500000" hp="15" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="2" fly="yes" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -565,7 +565,7 @@
     <skill name="cartmaking" modifier="-99"/>
     <attack type="4" damage="2d3"/>
   </race>
-  <race name="tunnelworm" magres="80" maxaura="0.000000" regaura="0.000000" weight="30000" capacity="10000" speed="1.0" hp="300" ac="6" damage="3d20" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="1" scarepeasants="yes" walk="yes" teach="no" getitem="yes">
+  <race name="tunnelworm" magres="80" maxaura="0.000000" regaura="0.000000" weight="30000" capacity="10000" speed="1.0" hp="300" ac="6" damage="3d20" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="1" scarepeasants="yes" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="99999"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="10"/>
@@ -589,15 +589,15 @@
     <attack type="4" damage="3d20"/>
     <attack type="8" damage="1d10"/>
   </race>
-  <race name="direwolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="20" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" teach="no" giveperson="yes">
+  <race name="direwolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="20" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" canteach="no" giveperson="yes">
     <ai splitsize="5000"/>
     <attack type="4" damage="2d4"/>
   </race>
-  <race name="peasant" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="20" damage="1d6" unarmedattack="0" unarmeddefense="0" cannotmove="yes" teach="no">
+  <race name="peasant" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="20" damage="1d6" unarmedattack="0" unarmeddefense="0" cannotmove="yes" canteach="no">
     <ai splitsize="10000"/>
     <attack type="1" damage="1d6"/>
   </race>
-  <race name="braineater" magres="90" maxaura="1.0" regaura="1.0" weight="100" capacity="540" speed="1.0" hp="20" damage="0d0" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" teach="no" invinciblenonmagic="yes">
+  <race name="braineater" magres="90" maxaura="1.0" regaura="1.0" weight="100" capacity="540" speed="1.0" hp="20" damage="0d0" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" canteach="no" invinciblenonmagic="yes">
     <ai splitsize="500" killpeasants="yes" moverandom="yes" learn="yes"/>
     <attack type="2" damage="3d15"/>
     <attack type="3" damage="1d1"/>
@@ -651,28 +651,28 @@
     <skill name="stamina" modifier="-10"/>
     <attack type="4" damage="1d2"/>
   </race>
-  <race name="mountainguard" unarmedguard="yes" magres="50" maxaura="1.0" regaura="0.500000" weight="10000" capacity="2000" speed="0.000000" hp="1000" ac="12" damage="2d40" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="8" cannotmove="yes" canlearn="no" teach="no" noweapons="yes">
+  <race name="mountainguard" unarmedguard="yes" magres="50" maxaura="1.0" regaura="0.500000" weight="10000" capacity="2000" speed="0.000000" hp="1000" ac="12" damage="2d40" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="8" cannotmove="yes" canlearn="no" canteach="no" noweapons="yes">
     <ai splitsize="1"/>
     <attack type="4" damage="2d40"/>
   </race>
-  <race name="shadowmaster" cansail="no" cansteal="no" canlearn="no" magres="75" maxaura="1.0" regaura="2.000000" weight="500" capacity="540" speed="1.0" hp="150" ac="4" damage="2d5" unarmedattack="0" unarmeddefense="0" attackmodifier="11" defensemodifier="13" scarepeasants="yes" walk="yes" teach="no" desert="yes">
+  <race name="shadowmaster" cansail="no" cansteal="no" canlearn="no" magres="75" maxaura="1.0" regaura="2.000000" weight="500" capacity="540" speed="1.0" hp="150" ac="4" damage="2d5" unarmedattack="0" unarmeddefense="0" attackmodifier="11" defensemodifier="13" scarepeasants="yes" walk="yes" canteach="no" desert="yes">
     <ai splitsize="50" killpeasants="yes" moverandom="yes" learn="yes"/>
     <attack type="4" damage="2d4"/>
     <attack type="2" damage="2d30"/>
     <attack type="3" damage="1d2"/>
   </race>
-  <race name="shadowdemon" cansail="no" cansteal="no" canlearn="no" magres="75" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="50" ac="3" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="8" defensemodifier="11" scarepeasants="yes" walk="yes" teach="no" desert="yes" recruitethereal="yes">
+  <race name="shadowdemon" cansail="no" cansteal="no" canlearn="no" magres="75" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="50" ac="3" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="8" defensemodifier="11" scarepeasants="yes" walk="yes" canteach="no" desert="yes" recruitethereal="yes">
     <ai splitsize="1000" killpeasants="yes" moverandom="yes" learn="yes"/>
     <attack type="4" damage="2d3"/>
     <attack type="3" damage="1d1"/>
   </race>
-  <race name="stonegolem" stonegolem="true" magres="25" maxaura="1.0" regaura="0.100000" weight="10000" capacity="2000" speed="1.0" hp="60" ac="4" damage="2d12+6" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" canlearn="no" teach="no">
+  <race name="stonegolem" stonegolem="true" magres="25" maxaura="1.0" regaura="0.100000" weight="10000" capacity="2000" speed="1.0" hp="60" ac="4" damage="2d12+6" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" canlearn="no" canteach="no">
     <ai splitsize="50"/>
     <skill name="building" modifier="14"/>
     <skill name="roadwork" modifier="14"/>
     <attack type="4" damage="2d10+4"/>
   </race>
-  <race name="irongolem" irongolem="true" magres="25" maxaura="1.0" regaura="0.100000" weight="10000" capacity="2000" speed="1.0" hp="50" ac="2" damage="2d10+4" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" canlearn="no" teach="no">
+  <race name="irongolem" irongolem="true" magres="25" maxaura="1.0" regaura="0.100000" weight="10000" capacity="2000" speed="1.0" hp="50" ac="2" damage="2d10+4" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" canlearn="no" canteach="no">
     <ai splitsize="50"/>
     <skill name="armorer" modifier="14"/>
     <skill name="weaponsmithing" modifier="14"/>
@@ -687,14 +687,14 @@
     <attack type="1" damage="1d4"/>
   </race>
 
-  <race name="dracoid" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="24" damage="1d5" unarmedattack="-2" unarmeddefense="-2" walk="yes" teach="no" giveperson="yes" getitem="yes" equipment="yes">
+  <race name="dracoid" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="24" damage="1d5" unarmedattack="-2" unarmeddefense="-2" walk="yes" canteach="no" giveperson="yes" getitem="yes" equipment="yes">
     <ai splitsize="10000" moverandom="yes" learn="yes"/>
     <attack type="4" damage="1d6"/>
     <attack type="4" damage="1d6"/>
     <attack type="1" damage="1d5"/>
   </race>
 
-  <race name="ent" magres="25" maxaura="1.0" regaura="0.500000" weight="5000" capacity="2500" speed="1.0" hp="50" ac="4" damage="2d4+12" unarmedattack="0" unarmeddefense="0" attackmodifier="9" defensemodifier="7" scarepeasants="yes" walk="yes" teach="no">
+  <race name="ent" magres="25" maxaura="1.0" regaura="0.500000" weight="5000" capacity="2500" speed="1.0" hp="50" ac="4" damage="2d4+12" unarmedattack="0" unarmeddefense="0" attackmodifier="9" defensemodifier="7" scarepeasants="yes" walk="yes" canteach="no">
     <ai splitsize="1000" moverandom="yes" learn="yes"/>
     <attack type="4" damage="2d12"/>
     <attack type="4" damage="2d12"/>
@@ -703,14 +703,14 @@
   <race name="undead" maxaura="1.0" regaura="1.0" weight="1000"
   capacity="540" speed="1.0" hp="20" damage="1d7" unarmedattack="0"
   unarmeddefense="0" attackmodifier="1" defensemodifier="1"
-  scarepeasants="yes" walk="yes" canlearn="no" teach="no" noheal="yes"
+  scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noheal="yes"
   undead="yes" equipment="yes" giveperson="yes">
     <ai splitsize="20000" moverandom="yes"/>
     <attack type="4" damage="1d7"/>
     <attack type="5"/>
   </race>
 
-  <race name="clone" magres="90" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.0" hp="40" damage="0d0" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" canlearn="no" teach="no" noheal="yes">
+  <race name="clone" magres="90" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.0" hp="40" damage="0d0" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" canlearn="no" canteach="no" noheal="yes">
     <ai splitsize="10000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -736,7 +736,7 @@
     <attack type="1" damage="0d0"/>
   </race>
 
-  <race name="ghast" magres="60" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="60" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
+  <race name="ghast" magres="60" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="60" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
     <ai splitsize="2000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -754,7 +754,7 @@
     <attack type="2" damage="1d30"/>
   </race>
 
-  <race name="ghoul" magres="30" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="30" ac="1" damage="1d7" unarmedattack="3" unarmeddefense="3" attackmodifier="3" defensemodifier="3" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
+  <race name="ghoul" magres="30" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="30" ac="1" damage="1d7" unarmedattack="3" unarmeddefense="3" attackmodifier="3" defensemodifier="3" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
     <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -771,7 +771,7 @@
     <attack type="2" damage="1d30"/>
   </race>
 
-  <race name="juju" magres="50" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="80" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistbash="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="juju" magres="50" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="80" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistbash="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="2000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -787,7 +787,7 @@
     <attack type="3" damage="1d1"/>
   </race>
 
-  <race name="zombie" magres="20" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="40" ac="1" damage="1d7" unarmedattack="2" unarmeddefense="2" attackmodifier="5" defensemodifier="5" scarepeasants="yes" walk="yes" canlearn="no" teach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="zombie" magres="20" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="40" ac="1" damage="1d7" unarmedattack="2" unarmeddefense="2" attackmodifier="5" defensemodifier="5" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -801,7 +801,7 @@
     <attack type="1" damage="1d7"/>
   </race>
 
-  <race name="skeletonlord" magres="30" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="60" ac="4" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="skeletonlord" magres="30" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="60" ac="4" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="2000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -816,7 +816,7 @@
     <attack type="1" damage="1d7"/>
   </race>
 
-  <race name="skeleton" magres="10" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="20" ac="1" damage="1d7" unarmedattack="1" unarmeddefense="1" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" teach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="skeleton" magres="10" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="20" ac="1" damage="1d7" unarmedattack="1" unarmeddefense="1" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -830,12 +830,12 @@
     <attack type="1" damage="1d7"/>
   </race>
 
-  <race name="shadowknight" maxaura="0.000000" regaura="0.000000" weight="0" capacity="540" speed="1.0" hp="1" damage="1d1" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" walk="yes" canlearn="no" teach="no" noblock="yes">
+  <race name="shadowknight" maxaura="0.000000" regaura="0.000000" weight="0" capacity="540" speed="1.0" hp="1" damage="1d1" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noblock="yes">
     <ai splitsize="20000" moverandom="yes"/>
     <attack type="1" damage="1d1"/>
   </race>
 
-  <race name="seaserpent" magres="50" maxaura="1.0" regaura="1.0" weight="20000" capacity="5000" speed="1.0" hp="600" ac="3" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" scarepeasants="yes" swim="yes" teach="no" getitem="yes" resistbash="yes">
+  <race name="seaserpent" magres="50" maxaura="1.0" regaura="1.0" weight="20000" capacity="5000" speed="1.0" hp="600" ac="3" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" scarepeasants="yes" swim="yes" canteach="no" getitem="yes" resistbash="yes">
     <ai splitsize="6" killpeasants="yes" moverandom="yes" learn="yes" moveattack="yes"/>
     <skill name="tactics" modifier="4"/>
     <attack type="4" damage="1d30"/>
diff --git a/res/eressea.dtd b/res/eressea.dtd
new file mode 100644
index 000000000..c58ea5f33
--- /dev/null
+++ b/res/eressea.dtd
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- DTD generated by XMLSpy v2018 rel. 2 (x64) (http://www.altova.com) -->
+<!ELEMENT ai EMPTY>
+<!ATTLIST ai
+	splitsize (1 | 1000 | 10000 | 2 | 2000 | 20000 | 50 | 500 | 5000 | 6 | 9999 | 99999) #REQUIRED
+	moverandom CDATA #FIXED "yes"
+	learn CDATA #FIXED "yes"
+	killpeasants CDATA #FIXED "yes"
+	moveattack CDATA #FIXED "yes"
+>
+<!ELEMENT set ((item+, ((skill+, item*) | callback | subset+)?) | (skill+, ((item+, subset?) | callback | subset | spell+)?) | callback)?>
+<!ATTLIST set
+	name (fam_direwolf | fam_dreamcat | fam_eagle | fam_fairy | fam_ghost | fam_hellcat | fam_imp | fam_lynx | fam_nymph | fam_owl | fam_rat | fam_songdragon | fam_tiger | fam_tunnelworm | fam_unicorn | i_bow | i_chain | i_plate | i_rustyshield | i_spear | i_sword | new_dracoid | new_orc | rand_bow | rand_crossbow | rand_desert | rand_forest | rand_glacier | rand_herbalist | rand_highland | rand_mountain | rand_plain | rand_rider | rand_spear | rand_swamp | rand_sword | rand_villagers | rising_undead | seed_aquarian | seed_braineater | seed_cat | seed_demon | seed_dragon | seed_dwarf | seed_elf | seed_goblin | seed_halfling | seed_human | seed_insect | seed_orc | seed_seaserpent | seed_troll | spo_dragon | spo_seaserpent | spo_wyrm | spo_youngdragon) #REQUIRED
+	chance (0.25 | 0.33 | 0.34) #IMPLIED
+>
+<!ELEMENT item (weapon?)>
+<!ATTLIST item
+	name (axe | balm | bow | cart | chainmail | crossbow | dragonblood | dragonhead | fairyboot | horse | incense | jewel | money | myrrh | nestwarmth | oil | plate | roi | rustychainmail | rustyshield | rustysword | seaserpenthead | silk | spear | spice | stone | sword | wagon) #IMPLIED
+	amount CDATA #IMPLIED
+	notlost CDATA #FIXED "yes"
+	weight (0 | 1 | 100) #IMPLIED
+	use CDATA #FIXED "yes"
+	cursed (true | yes) #IMPLIED
+	score CDATA #FIXED "0"
+>
+<!ELEMENT race ((ai, ((skill+, attack+, familiar*) | (param, skill+, attack, familiar+) | attack+)) | attack+)>
+<!ATTLIST race
+	name (aquarian | braineater | cat | catdragon | clone | demon | direwolf | dolphin | dracoid | dragon | dreamcat | dwarf | eagle | elf | ent | fairy | ghast | ghost | ghoul | giantturtle | gnome | goblin | halfling | hellcat | human | imp | insect | irongolem | juju | kraken | lynx | mountainguard | museumghost | nymph | orc | owl | peasant | rat | seaserpent | shadowdemon | shadowdragon | shadowknight | shadowmaster | skeleton | skeletonlord | smurf | snotling | snowman | songdragon | special | spell | stonegolem | template | tiger | toad | troll | tunnelworm | undead | unicorn | wolf | wyrm | youngdragon | zombie) #REQUIRED
+	magres (-0.050000 | -5 | 10 | 100 | 15 | 20 | 25 | 30 | 5 | 50 | 60 | 70 | 75 | 80 | 90 | 95 | 99) #IMPLIED
+	maxaura (0.000000 | 0.500000 | 1.000000 | 1.500000) #IMPLIED
+	regaura (0.000000 | 0.100000 | 0.500000 | 1.000000 | 1.250000 | 1.500000 | 2.000000 | 3.000000) #IMPLIED
+	weight (0 | 100 | 1000 | 10000 | 1600 | 18000 | 200 | 2000 | 20000 | 30000 | 500 | 5000 | 600) #REQUIRED
+	capacity (0 | 1000 | 10000 | 100000 | 1000000 | 1080 | 200 | 2000 | 2500 | 440 | 5000 | 540 | 600) #REQUIRED
+	equipment (no | yes) #IMPLIED
+	speed (0.000000 | 1.000000 | 1.500000 | 10.000000 | 2.000000) #REQUIRED
+	hp (1 | 10 | 1000 | 15 | 150 | 16 | 18 | 20 | 24 | 25 | 2700 | 30 | 300 | 40 | 50 | 6 | 60 | 600 | 80 | 9 | 900) #REQUIRED
+	ac (1 | 10 | 12 | 2 | 3 | 4 | 5 | 6 | 7 | 8) #IMPLIED
+	damage CDATA #REQUIRED
+	unarmedattack (-2 | 0 | 1 | 10 | 2 | 3 | 6) #REQUIRED
+	unarmeddefense (-2 | 0 | 1 | 10 | 2 | 3 | 6) #REQUIRED
+	attackmodifier (1 | 10 | 11 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9) #IMPLIED
+	defensemodifier (1 | 10 | 11 | 12 | 13 | 14 | 2 | 3 | 4 | 5 | 50 | 6 | 7 | 8) #IMPLIED
+	fly (no | yes) #IMPLIED
+	walk (no | yes) #IMPLIED
+	canteach CDATA #FIXED "no"
+	getitem CDATA #FIXED "yes"
+	recruitcost (110 | 130 | 150 | 40 | 70 | 75 | 80 | 90) #IMPLIED
+	maintenance (0 | 10) #IMPLIED
+	playerrace (no | yes) #IMPLIED
+	giveperson CDATA #FIXED "yes"
+	giveunit CDATA #FIXED "yes"
+	coastal CDATA #FIXED "yes"
+	swim CDATA #FIXED "yes"
+	teach CDATA #FIXED "no"
+	resistpierce CDATA #FIXED "yes"
+	invinciblenonmagic CDATA #FIXED "yes"
+	scarepeasants CDATA #FIXED "yes"
+	unarmedguard CDATA #FIXED "yes"
+	cannotmove CDATA #FIXED "yes"
+	canlearn CDATA #FIXED "no"
+	noweapons CDATA #FIXED "yes"
+	cansail CDATA #FIXED "no"
+	cansteal CDATA #FIXED "no"
+	desert CDATA #FIXED "yes"
+	recruitethereal CDATA #FIXED "yes"
+	stonegolem CDATA #FIXED "true"
+	irongolem CDATA #FIXED "true"
+	noheal CDATA #FIXED "yes"
+	illusionary CDATA #FIXED "yes"
+	invisible CDATA #FIXED "yes"
+	shapeshift CDATA #FIXED "yes"
+	dragon CDATA #FIXED "yes"
+	resistbash CDATA #FIXED "yes"
+	undead CDATA #FIXED "yes"
+	shipspeed CDATA #FIXED "yes"
+	shapeshiftany CDATA #FIXED "yes"
+	recruitunlimited CDATA #FIXED "yes"
+	absorbpeasants CDATA #FIXED "yes"
+	resistcut CDATA #FIXED "yes"
+	noblock CDATA #FIXED "yes"
+	studyspeed CDATA #FIXED "-5"
+>
+<!ELEMENT text (#PCDATA)>
+<!ATTLIST text
+	locale (de | en | fr) #REQUIRED
+>
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+	name (hunger.damage | migrants.formula | recruit_multi) #REQUIRED
+	value CDATA #REQUIRED
+>
+<!ELEMENT races (race+)>
+<!ELEMENT skill EMPTY>
+<!ATTLIST skill
+	name (alchemy | armorer | bow | building | cartmaking | catapult | crossbow | entertainment | espionage | forestry | herbalism | magic | melee | mining | perception | polearm | quarrying | riding | roadwork | sailing | shipcraft | stamina | stealth | tactics | taxation | trade | training | unarmed | weaponsmithing) #REQUIRED
+	level CDATA #IMPLIED
+	modifier (-1 | -10 | -2 | -3 | -99 | 1 | 10 | 12 | 14 | 2 | 20 | 3 | 4 | 5 | 8) #IMPLIED
+>
+<!ELEMENT spell (#PCDATA | resource)*>
+<!ATTLIST spell
+	name CDATA #REQUIRED
+	level (1 | 12 | 2 | 3 | 4 | 5 | 6 | 7 | 8) #IMPLIED
+	ship CDATA #FIXED "true"
+	rank (1 | 2 | 3 | 4 | 5 | 7) #IMPLIED
+	variable CDATA #FIXED "true"
+	combat (1 | 2 | 3) #IMPLIED
+	parameters CDATA #IMPLIED
+	los CDATA #FIXED "true"
+	far CDATA #FIXED "true"
+	ocean CDATA #FIXED "true"
+	syntax (aura | buildingtype | direction | race | spellid) #IMPLIED
+	regiontarget (false | true) #IMPLIED
+	unittarget CDATA #FIXED "false"
+	buildingtarget CDATA #FIXED "true"
+	shiptarget CDATA #FIXED "true"
+	globaltarget CDATA #FIXED "true"
+>
+<!ELEMENT attack EMPTY>
+<!ATTLIST attack
+	type (1 | 2 | 3 | 4 | 5 | 6 | 8) #REQUIRED
+	damage CDATA #IMPLIED
+	spell (aura_of_fear | drain_skills | fiery_dragonbreath | icy_dragonbreath | powerful_dragonbreath) #IMPLIED
+	level (12 | 3 | 6) #IMPLIED
+>
+<!ELEMENT damage EMPTY>
+<!ATTLIST damage
+	type (footman | rider) #REQUIRED
+	value CDATA #FIXED "3d8+8"
+>
+<!ELEMENT spells (spell+)>
+<!ELEMENT string (text+)>
+<!ATTLIST string
+	name (adamantium | adamantium_p | adamantiumaxe | adamantiumaxe_p | adamantiumplate | adamantiumplate_p | almond | analysedream | aoc | aoc_p | apple | artacademy | aurapotion50 | aurapotion50_p | bagpipeoffear | bagpipeoffear_p | balloon | birthdaycake | birthdaycake_p | cookie | eyeofdragon | headache | jadee_dress | jadee_dress_p | jadee_ring | jadee_ring_p | lifepotion | newbie_info_cr | nut | pavilion | portal | ring | ring_of_levitation | ring_of_levitation_p | ring_p | rm_adamantium | seaserpenthead | seaserpenthead_p | seashell | seashell_p | snowball | snowman | snowman_p | stardust | temple | wente_dress | wente_dress_p | wente_ring | wente_ring_p | xmastree) #REQUIRED
+>
+<!ELEMENT subset (set+)>
+<!ATTLIST subset
+	chance (0.2 | 0.3 | 0.4 | 0.6) #IMPLIED
+>
+<!ELEMENT weapon (damage+, modifier+)>
+<!ATTLIST weapon
+	bash CDATA #FIXED "true"
+	missile CDATA #FIXED "true"
+	skill CDATA #FIXED "unarmed"
+	offmod CDATA #FIXED "0"
+	defmod CDATA #FIXED "0"
+	reload CDATA #FIXED "0"
+	magres CDATA #FIXED "0.0"
+>
+<!ELEMENT eressea (equipment+, buildings, resources, races, strings, spells)>
+<!ELEMENT strings (namespace+, string+)>
+<!ELEMENT building EMPTY>
+<!ATTLIST building
+	name (artacademy | pavilion | portal | temple) #REQUIRED
+	maxsize (100 | 2 | 50) #REQUIRED
+	maxcapacity CDATA #FIXED "2"
+	nobuild CDATA #FIXED "yes"
+	nodestroy CDATA #FIXED "yes"
+	unique CDATA #FIXED "yes"
+	auraregen CDATA #FIXED "1.00"
+>
+<!ELEMENT callback EMPTY>
+<!ATTLIST callback
+	name CDATA #FIXED "equip_newunits"
+>
+<!ELEMENT familiar EMPTY>
+<!ATTLIST familiar
+	race (demon | dolphin | dreamcat | eagle | fairy | ghost | giantturtle | goblin | hellcat | imp | kraken | lynx | nymph | owl | rat | songdragon | tiger | tunnelworm | unicorn | wolf) #REQUIRED
+	default CDATA #FIXED "yes"
+>
+<!ELEMENT modifier EMPTY>
+<!ATTLIST modifier
+	type (missile_target | skill) #REQUIRED
+	value (-90 | 100 | 2) #REQUIRED
+	races CDATA #FIXED "snowman"
+>
+<!ELEMENT resource (item?)>
+<!ATTLIST resource
+	name (almond | aoc | aog | apple | aura | birthdaycake | cookie | dragonblood | dragonhead | eyeofdragon | h12 | h20 | h7 | hp | iron | jadee_dress | jadee_ring | laen | laensword | lebkuchenherz | lifepotion | lmsreward | log | mallorn | money | museumexitticket | museumticket | nut | oil | p10 | peasant | permaura | questkey1 | questkey2 | ring_of_levitation | seaserpenthead | seashell | snowball | snowglobe | snowman | stardust | stone | sword | toadslime | wente_dress | wente_ring | xmastree) #REQUIRED
+	appearance (amulet | key | ring | vial) #IMPLIED
+	amount (1 | 10 | 100 | 1000 | 12 | 140 | 15 | 150 | 16 | 18 | 2 | 20 | 200 | 24 | 25 | 250 | 28 | 3 | 30 | 3000 | 30000 | 35 | 350 | 4 | 40 | 4000 | 5 | 50 | 5000 | 6 | 600 | 7 | 8 | 80 | 800 | 90) #IMPLIED
+	cost (fixed | level) #IMPLIED
+>
+<!ELEMENT buildings (building+)>
+<!ELEMENT equipment (set+)>
+<!ELEMENT namespace (string+)>
+<!ATTLIST namespace
+	name (describe | iteminfo | race | shipinfo | spell | spellinfo) #REQUIRED
+>
+<!ELEMENT resources (resource+)>
diff --git a/res/eressea/races.xml b/res/eressea/races.xml
index 21ff5b028..eb85b6900 100644
--- a/res/eressea/races.xml
+++ b/res/eressea/races.xml
@@ -11,9 +11,8 @@
     <attack type="3" damage="2d6+2"/>
   </race>
 
-  <race name="human" maxaura="1.000000" regaura="1.000000" recruitcost="75" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
+  <race name="human" maxaura="1.000000" regaura="1.000000" recruitcost="75" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes" migrants="yes">
     <ai splitsize="10000" moverandom="yes" learn="yes"/>
-    <param name="migrants.formula" value="1"/>
     <skill name="trade" modifier="1"/>
     <skill name="herbalism" modifier="-1"/>
     <skill name="shipcraft" modifier="1"/>
@@ -27,7 +26,7 @@
     <familiar race="eagle"/>
     <familiar race="imp"/>
   </race>
-  <race name="kraken" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="300" damage="2d10" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" coastal="yes" swim="yes" teach="no" getitem="yes">
+  <race name="kraken" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="300" damage="2d10" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" coastal="yes" swim="yes" canteach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="perception" modifier="1"/>
     <skill name="alchemy" modifier="-99"/>
@@ -60,7 +59,7 @@
     <attack type="4" damage="1d10"/>
     <attack type="4" damage="1d10"/>
   </race>
-  <race name="giantturtle" maxaura="0.000000" regaura="0.000000" weight="1600" capacity="600" speed="1.000000" hp="900" ac="7" damage="2d50" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="5" coastal="yes" swim="yes" walk="yes" teach="no" getitem="yes">
+  <race name="giantturtle" maxaura="0.000000" regaura="0.000000" weight="1600" capacity="600" speed="1.000000" hp="900" ac="7" damage="2d50" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="5" coastal="yes" swim="yes" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="perception" modifier="1"/>
     <skill name="alchemy" modifier="-99"/>
@@ -88,7 +87,7 @@
     <skill name="taxation" modifier="-99"/>
     <attack type="4" damage="2d50"/>
   </race>
-  <race name="dolphin" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="24" damage="1d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="5" coastal="yes" swim="yes" teach="no" getitem="yes">
+  <race name="dolphin" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="24" damage="1d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="5" coastal="yes" swim="yes" canteach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -115,7 +114,7 @@
     <skill name="taxation" modifier="-99"/>
     <attack type="4" damage="1d6"/>
   </race>
-  <race name="tiger" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="30" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" walk="yes" teach="no" getitem="yes">
+  <race name="tiger" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="30" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -144,7 +143,7 @@
     <attack type="4" damage="1d6"/>
     <attack type="4" damage="1d6"/>
   </race>
-  <race name="hellcat" magres="50" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="40" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" teach="no" getitem="yes" resistpierce="yes">
+  <race name="hellcat" magres="50" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="40" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" canteach="no" getitem="yes" resistpierce="yes">
     <ai splitsize="5000"/>
     <skill name="perception" modifier="1"/>
     <skill name="alchemy" modifier="-99"/>
@@ -173,7 +172,7 @@
     <attack type="4" damage="1d6"/>
     <attack type="4" damage="1d6"/>
   </race>
-  <race name="owl" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="9" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="2" defensemodifier="4" fly="yes" walk="yes" teach="no" getitem="yes">
+  <race name="owl" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="9" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="2" defensemodifier="4" fly="yes" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="espionage" modifier="1"/>
     <skill name="stealth" modifier="1"/>
@@ -203,7 +202,7 @@
     <skill name="taxation" modifier="-99"/>
     <attack type="4" damage="1d4"/>
   </race>
-  <race name="fairy" magres="80" maxaura="1.000000" regaura="1.500000" weight="200" capacity="540" speed="1.000000" hp="6" damage="1d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="14" fly="yes" walk="yes" teach="no" getitem="yes" equipment="yes">
+  <race name="fairy" magres="80" maxaura="1.000000" regaura="1.500000" weight="200" capacity="540" speed="1.000000" hp="6" damage="1d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="14" fly="yes" walk="yes" canteach="no" getitem="yes" equipment="yes">
     <ai splitsize="5000"/>
     <skill name="stealth" modifier="5"/>
     <skill name="espionage" modifier="2"/>
@@ -237,7 +236,7 @@
     <attack type="4" damage="1d3"/>
     <attack type="4" damage="1d3"/>
   </race>
-  <race name="dreamcat" magres="50" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="10" damage="1d5" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="6" fly="yes" walk="yes" teach="no" getitem="yes" invinciblenonmagic="yes">
+  <race name="dreamcat" magres="50" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="10" damage="1d5" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="6" fly="yes" walk="yes" canteach="no" getitem="yes" invinciblenonmagic="yes">
     <ai splitsize="5000"/>
     <skill name="magic" modifier="1"/>
     <skill name="espionage" modifier="1"/>
@@ -267,7 +266,7 @@
     <attack type="4" damage="1d5"/>
     <attack type="4" damage="1d5"/>
   </race>
-  <race name="imp" magres="50" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="10" ac="1" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="4" fly="yes" walk="yes" teach="no" getitem="yes" equipment="yes">
+  <race name="imp" magres="50" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="10" ac="1" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="4" fly="yes" walk="yes" canteach="no" getitem="yes" equipment="yes">
     <ai splitsize="5000"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -299,7 +298,7 @@
     <attack type="1" damage="1d4"/>
     <attack type="6" spell="fiery_dragonbreath" level="3" />
   </race>
-  <race name="ghost" magres="80" maxaura="0.500000" regaura="0.100000" weight="500" capacity="540" speed="1.000000" hp="30" ac="5" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="8" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" equipment="yes" invinciblenonmagic="yes">
+  <race name="ghost" magres="80" maxaura="0.500000" regaura="0.100000" weight="500" capacity="540" speed="1.000000" hp="30" ac="5" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="8" scarepeasants="yes" fly="yes" walk="yes" canteach="no" getitem="yes" equipment="yes" invinciblenonmagic="yes">
     <ai splitsize="5000"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -329,7 +328,7 @@
     <attack type="2" damage="2d30"/>
     <attack type="3" damage="1d1"/>
   </race>
-  <race name="wolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="25" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" scarepeasants="yes" walk="yes" teach="no" getitem="yes">
+  <race name="wolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="25" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" scarepeasants="yes" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -358,7 +357,7 @@
     <attack type="4" damage="1d4"/>
     <attack type="4" damage="1d4"/>
   </race>
-  <race name="unicorn" magres="90" maxaura="1.500000" regaura="1.500000" weight="5000" capacity="2000" speed="2.000000" hp="40" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" teach="no" getitem="yes">
+  <race name="unicorn" magres="90" maxaura="1.500000" regaura="1.500000" weight="5000" capacity="2000" speed="2.000000" hp="40" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -388,7 +387,7 @@
     <attack type="4" damage="3d12"/>
     <attack type="4" damage="2d4"/>
   </race>
-  <race name="nymph" magres="90" maxaura="1.000000" regaura="1.500000" weight="1000" capacity="540" speed="1.000000" hp="15" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" teach="no" getitem="yes" equipment="yes">
+  <race name="nymph" magres="90" maxaura="1.000000" regaura="1.500000" weight="1000" capacity="540" speed="1.000000" hp="15" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" canteach="no" getitem="yes" equipment="yes">
     <ai splitsize="9999"/>
     <skill name="mining" modifier="-99"/>
     <skill name="bow" modifier="2"/>
@@ -417,7 +416,7 @@
     <attack type="1" damage="1d4"/>
     <attack type="2" damage="2d20"/>
   </race>
-  <race name="songdragon" magres="99" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="600" speed="1.500000" hp="40" ac="1" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" fly="yes" walk="yes" teach="no" getitem="yes" unarmedguard="yes">
+  <race name="songdragon" magres="99" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="600" speed="1.500000" hp="40" ac="1" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" fly="yes" walk="yes" canteach="no" getitem="yes" unarmedguard="yes">
     <ai splitsize="9999"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -448,7 +447,7 @@
     <attack type="4" damage="2d4"/>
     <attack type="6" spell="fiery_dragonbreath" level="3" />
   </race>
-  <race name="rat" maxaura="0.000000" regaura="0.000000" weight="100" capacity="540" speed="1.000000" hp="10" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" walk="yes" teach="no" getitem="yes">
+  <race name="rat" maxaura="0.000000" regaura="0.000000" weight="100" capacity="540" speed="1.000000" hp="10" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="espionage" modifier="5"/>
     <skill name="stealth" modifier="4"/>
@@ -479,7 +478,7 @@
     <attack type="4" damage="1d4"/>
     <attack type="4" damage="1d4"/>
   </race>
-  <race name="eagle" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.500000" hp="15" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="2" fly="yes" walk="yes" teach="no" getitem="yes">
+  <race name="eagle" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.500000" hp="15" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="2" fly="yes" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -508,7 +507,7 @@
     <skill name="taxation" modifier="-99"/>
     <attack type="4" damage="2d3"/>
   </race>
-  <race name="tunnelworm" magres="80" maxaura="0.000000" regaura="0.000000" weight="30000" capacity="10000" speed="1.000000" hp="300" ac="6" damage="3d20" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="1" scarepeasants="yes" walk="yes" teach="no" getitem="yes">
+  <race name="tunnelworm" magres="80" maxaura="0.000000" regaura="0.000000" weight="30000" capacity="10000" speed="1.000000" hp="300" ac="6" damage="3d20" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="1" scarepeasants="yes" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="99999"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -540,7 +539,7 @@
     <attack type="4" damage="3d20"/>
     <attack type="8" damage="1d10"/>
   </race>
-  <race name="lynx" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="20" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="5" walk="yes" teach="no" getitem="yes">
+  <race name="lynx" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="20" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="5" walk="yes" canteach="no" getitem="yes">
     <ai splitsize="99999"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -570,16 +569,16 @@
     <skill name="taxation" modifier="-99"/>
     <attack type="4" damage="2d3"/>
   </race>
-  <race name="direwolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="20" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" teach="no" giveperson="yes">
+  <race name="direwolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="20" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" canteach="no" giveperson="yes">
     <ai splitsize="5000"/>
     <attack type="4" damage="2d4"/>
   </race>
-  <race name="peasant" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d6" unarmedattack="0" unarmeddefense="0" cannotmove="yes" teach="no">
+  <race name="peasant" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d6" unarmedattack="0" unarmeddefense="0" cannotmove="yes" canteach="no">
     <ai splitsize="10000"/>
     <attack type="1" damage="1d6"/>
   </race>
   <race name="braineater" magres="90" maxaura="1.000000"
-  regaura="1.000000" weight="100" capacity="540" speed="1.000000" hp="20" damage="0d0" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" teach="no" invinciblenonmagic="yes">
+  regaura="1.000000" weight="100" capacity="540" speed="1.000000" hp="20" damage="0d0" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" canteach="no" invinciblenonmagic="yes">
     <ai splitsize="500" killpeasants="yes" moverandom="yes" learn="yes"/>
     <attack type="2" damage="3d15"/>
     <attack type="3" damage="1d1"/>
@@ -649,28 +648,28 @@
     <skill name="stamina" modifier="-10"/>
     <attack type="4" damage="1d2"/>
   </race>
-  <race name="mountainguard" unarmedguard="yes" magres="50" maxaura="1.000000" regaura="0.500000" weight="10000" capacity="2000" speed="0.000000" hp="1000" ac="12" damage="2d40" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="8" cannotmove="yes" canlearn="no" teach="no" noweapons="yes">
+  <race name="mountainguard" unarmedguard="yes" magres="50" maxaura="1.000000" regaura="0.500000" weight="10000" capacity="2000" speed="0.000000" hp="1000" ac="12" damage="2d40" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="8" cannotmove="yes" canlearn="no" canteach="no" noweapons="yes">
     <ai splitsize="1"/>
     <attack type="4" damage="2d40"/>
   </race>
-  <race name="shadowmaster" cansail="no" cansteal="no" canlearn="no" magres="75" maxaura="1.000000" regaura="2.000000" weight="500" capacity="540" speed="1.000000" hp="150" ac="4" damage="2d5" unarmedattack="0" unarmeddefense="0" attackmodifier="11" defensemodifier="13" scarepeasants="yes" walk="yes" teach="no" desert="yes">
+  <race name="shadowmaster" cansail="no" cansteal="no" canlearn="no" magres="75" maxaura="1.000000" regaura="2.000000" weight="500" capacity="540" speed="1.000000" hp="150" ac="4" damage="2d5" unarmedattack="0" unarmeddefense="0" attackmodifier="11" defensemodifier="13" scarepeasants="yes" walk="yes" canteach="no" desert="yes">
     <ai splitsize="50" killpeasants="yes" moverandom="yes" learn="yes"/>
     <attack type="4" damage="2d4"/>
     <attack type="2" damage="2d30"/>
     <attack type="3" damage="1d2"/>
   </race>
-  <race name="shadowdemon" cansail="no" cansteal="no" canlearn="no" magres="75" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="50" ac="3" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="8" defensemodifier="11" scarepeasants="yes" walk="yes" teach="no" desert="yes" recruitethereal="yes">
+  <race name="shadowdemon" cansail="no" cansteal="no" canlearn="no" magres="75" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="50" ac="3" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="8" defensemodifier="11" scarepeasants="yes" walk="yes" canteach="no" desert="yes" recruitethereal="yes">
     <ai splitsize="1000" killpeasants="yes" moverandom="yes" learn="yes"/>
     <attack type="4" damage="2d3"/>
     <attack type="3" damage="1d1"/>
   </race>
-  <race name="stonegolem" stonegolem="true" magres="25" maxaura="1.000000" regaura="0.100000" weight="10000" capacity="2000" speed="1.000000" hp="60" ac="4" damage="2d12+6" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" canlearn="no" teach="no">
+  <race name="stonegolem" stonegolem="true" magres="25" maxaura="1.000000" regaura="0.100000" weight="10000" capacity="2000" speed="1.000000" hp="60" ac="4" damage="2d12+6" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" canlearn="no" canteach="no">
     <ai splitsize="50"/>
     <skill name="building" modifier="14"/>
     <skill name="roadwork" modifier="14"/>
     <attack type="4" damage="2d10+4"/>
   </race>
-  <race name="irongolem" irongolem="true" magres="25" maxaura="1.000000" regaura="0.100000" weight="10000" capacity="2000" speed="1.000000" hp="50" ac="2" damage="2d10+4" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" canlearn="no" teach="no">
+  <race name="irongolem" irongolem="true" magres="25" maxaura="1.000000" regaura="0.100000" weight="10000" capacity="2000" speed="1.000000" hp="50" ac="2" damage="2d10+4" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" canlearn="no" canteach="no">
     <ai splitsize="50"/>
     <skill name="armorer" modifier="14"/>
     <skill name="weaponsmithing" modifier="14"/>
@@ -684,25 +683,25 @@
     <ai splitsize="1"/>
     <attack type="1" damage="1d4"/>
   </race>
-  <race name="dracoid" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="24" damage="1d5" unarmedattack="-2" unarmeddefense="-2" walk="yes" teach="no" giveperson="yes" getitem="yes" equipment="yes">
+  <race name="dracoid" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="24" damage="1d5" unarmedattack="-2" unarmeddefense="-2" walk="yes" canteach="no" giveperson="yes" getitem="yes" equipment="yes">
     <ai splitsize="10000" moverandom="yes" learn="yes"/>
     <attack type="4" damage="1d6"/>
     <attack type="4" damage="1d6"/>
     <attack type="1" damage="1d5"/>
   </race>
-  <race name="catdragon" magres="90" maxaura="1.000000" regaura="1.000000" weight="20000" capacity="10000" speed="1.000000" hp="20" damage="2d40" unarmedattack="0" unarmeddefense="0" defensemodifier="50" fly="yes" walk="yes" teach="no" shapeshift="yes" giveperson="yes" getitem="yes" dragon="yes">
+  <race name="catdragon" magres="90" maxaura="1.000000" regaura="1.000000" weight="20000" capacity="10000" speed="1.000000" hp="20" damage="2d40" unarmedattack="0" unarmeddefense="0" defensemodifier="50" fly="yes" walk="yes" canteach="no" shapeshift="yes" giveperson="yes" getitem="yes" dragon="yes">
     <ai splitsize="1"/>
     <attack type="4" damage="2d40"/>
     <attack type="4" damage="2d40"/>
     <attack type="4" damage="2d40"/>
     <attack type="4" damage="2d40"/>
   </race>
-  <race name="ent" magres="25" maxaura="1.000000" regaura="0.500000" weight="5000" capacity="2500" speed="1.000000" hp="50" ac="4" damage="2d4+12" unarmedattack="0" unarmeddefense="0" attackmodifier="9" defensemodifier="7" scarepeasants="yes" walk="yes" teach="no">
+  <race name="ent" magres="25" maxaura="1.000000" regaura="0.500000" weight="5000" capacity="2500" speed="1.000000" hp="50" ac="4" damage="2d4+12" unarmedattack="0" unarmeddefense="0" attackmodifier="9" defensemodifier="7" scarepeasants="yes" walk="yes" canteach="no">
     <ai splitsize="1000" moverandom="yes" learn="yes"/>
     <attack type="4" damage="2d12"/>
     <attack type="4" damage="2d12"/>
   </race>
-  <race name="wyrm" magres="90" maxaura="1.000000" regaura="3.000000" weight="18000" capacity="1000000" speed="1.000000" hp="2700" ac="8" damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes" dragon="yes" unarmedguard="yes">
+  <race name="wyrm" magres="90" maxaura="1.000000" regaura="3.000000" weight="18000" capacity="1000000" speed="1.000000" hp="2700" ac="8" damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" canteach="no" getitem="yes" resistbash="yes" dragon="yes" unarmedguard="yes">
     <ai splitsize="1" killpeasants="yes" learn="yes"/>
     <skill name="magic" modifier="12"/>
     <skill name="tactics" modifier="12"/>
@@ -712,7 +711,7 @@
     <attack type="4" damage="5d30"/>
     <attack type="6" spell="powerful_dragonbreath" level="12" />
   </race>
-  <race name="dragon" magres="70" maxaura="1.000000" regaura="2.000000" weight="10000" capacity="1000000" speed="1.500000" hp="900" ac="6" damage="2d30" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes" unarmedguard="yes" dragon="yes">
+  <race name="dragon" magres="70" maxaura="1.000000" regaura="2.000000" weight="10000" capacity="1000000" speed="1.500000" hp="900" ac="6" damage="2d30" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" scarepeasants="yes" fly="yes" walk="yes" canteach="no" getitem="yes" resistbash="yes" unarmedguard="yes" dragon="yes">
     <ai splitsize="2" killpeasants="yes" learn="yes"/>
     <skill name="magic" modifier="8"/>
     <skill name="tactics" modifier="8"/>
@@ -722,7 +721,7 @@
     <attack type="4" damage="3d30"/>
     <attack type="6" spell="icy_dragonbreath" level="6" />
   </race>
-  <race name="youngdragon" magres="50" maxaura="1.000000" regaura="1.000000" weight="20000" capacity="10000" speed="1.000000" hp="300" ac="4" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes" unarmedguard="yes">
+  <race name="youngdragon" magres="50" maxaura="1.000000" regaura="1.000000" weight="20000" capacity="10000" speed="1.000000" hp="300" ac="4" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" scarepeasants="yes" fly="yes" walk="yes" canteach="no" getitem="yes" resistbash="yes" unarmedguard="yes">
     <ai splitsize="6" killpeasants="yes" learn="yes"/>
     <skill name="magic" modifier="4"/>
     <skill name="tactics" modifier="4"/>
@@ -733,7 +732,7 @@
     <attack type="4" damage="1d30"/>
     <attack type="6" spell="fiery_dragonbreath" level="3" />
   </race>
-  <race name="undead" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d7" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" walk="yes" canlearn="no" teach="no" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
+  <race name="undead" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d7" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
     <ai splitsize="20000" moverandom="yes"/>
     <attack type="4" damage="1d7"/>
     <attack type="5"/>
@@ -783,7 +782,7 @@
   </race>
   <race name="halfling" magres="5" maxaura="1.000000" regaura="1.000000" recruitcost="80" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="18" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
     <ai splitsize="10000" moverandom="yes" learn="yes"/>
-    <param name="hunger.damage" value="1d14+14"/>
+    <param name="hunger_damage" value="1d14+14"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="mining" modifier="1"/>
     <skill name="bow" modifier="-1"/>
@@ -925,7 +924,7 @@
     <familiar race="rat"/>
     <familiar race="imp"/>
   </race>
-  <race name="clone" magres="90" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.000000" hp="40" damage="0d0" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" canlearn="no" teach="no" noheal="yes">
+  <race name="clone" magres="90" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.000000" hp="40" damage="0d0" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" canlearn="no" canteach="no" noheal="yes">
     <ai splitsize="10000"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -962,7 +961,7 @@
     <ai splitsize="10000" moverandom="yes" learn="yes"/>
     <attack type="1" damage="1d4"/>
   </race>
-  <race name="gnome" magres="100" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.000000" hp="50" damage="1d4" unarmedattack="10" unarmeddefense="10" attackmodifier="10" defensemodifier="10" walk="yes" teach="no">
+  <race name="gnome" magres="100" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.000000" hp="50" damage="1d4" unarmedattack="10" unarmeddefense="10" attackmodifier="10" defensemodifier="10" walk="yes" canteach="no">
     <ai splitsize="10000"/>
     <skill name="tactics" modifier="1"/>
     <skill name="perception" modifier="1"/>
@@ -970,7 +969,7 @@
     <skill name="unarmed" modifier="1"/>
     <attack type="1" damage="1d4"/>
   </race>
-  <race name="museumghost" magres="100" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.000000" hp="50" damage="1d4" unarmedattack="10" unarmeddefense="10" attackmodifier="10" defensemodifier="10" walk="yes" teach="no">
+  <race name="museumghost" magres="100" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.000000" hp="50" damage="1d4" unarmedattack="10" unarmeddefense="10" attackmodifier="10" defensemodifier="10" walk="yes" canteach="no">
     <ai splitsize="10000"/>
     <skill name="tactics" modifier="1"/>
     <skill name="perception" modifier="1"/>
@@ -984,7 +983,7 @@
     <attack type="2" damage="5d600"/>
     <attack type="1" damage="1d4"/>
   </race>
-  <race name="ghast" magres="60" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="60" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
+  <race name="ghast" magres="60" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="60" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
     <ai splitsize="2000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -1001,7 +1000,7 @@
     <attack type="2" damage="1d30"/>
     <attack type="2" damage="1d30"/>
   </race>
-  <race name="ghoul" magres="30" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="30" ac="1" damage="1d7" unarmedattack="3" unarmeddefense="3" attackmodifier="3" defensemodifier="3" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
+  <race name="ghoul" magres="30" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="30" ac="1" damage="1d7" unarmedattack="3" unarmeddefense="3" attackmodifier="3" defensemodifier="3" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
     <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -1017,7 +1016,7 @@
     <attack type="3" damage="1d2"/>
     <attack type="2" damage="1d30"/>
   </race>
-  <race name="juju" magres="50" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="80" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistbash="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="juju" magres="50" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="80" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistbash="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="2000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -1032,7 +1031,7 @@
     <attack type="3" damage="1d1"/>
     <attack type="3" damage="1d1"/>
   </race>
-  <race name="zombie" magres="20" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="40" ac="1" damage="1d7" unarmedattack="2" unarmeddefense="2" attackmodifier="5" defensemodifier="5" scarepeasants="yes" walk="yes" canlearn="no" teach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="zombie" magres="20" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="40" ac="1" damage="1d7" unarmedattack="2" unarmeddefense="2" attackmodifier="5" defensemodifier="5" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -1045,7 +1044,7 @@
     <skill name="unarmed" modifier="1"/>
     <attack type="1" damage="1d7"/>
   </race>
-  <race name="skeletonlord" magres="30" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="60" ac="4" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="skeletonlord" magres="30" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="60" ac="4" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="2000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -1059,7 +1058,7 @@
     <attack type="1" damage="1d7"/>
     <attack type="1" damage="1d7"/>
   </race>
-  <race name="skeleton" magres="10" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="20" ac="1" damage="1d7" unarmedattack="1" unarmeddefense="1" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" teach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="skeleton" magres="10" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="20" ac="1" damage="1d7" unarmedattack="1" unarmeddefense="1" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -1072,11 +1071,11 @@
     <skill name="unarmed" modifier="1"/>
     <attack type="1" damage="1d7"/>
   </race>
-  <race name="shadowknight" maxaura="0.000000" regaura="0.000000" weight="0" capacity="540" speed="1.000000" hp="1" damage="1d1" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" walk="yes" canlearn="no" teach="no" noblock="yes">
+  <race name="shadowknight" maxaura="0.000000" regaura="0.000000" weight="0" capacity="540" speed="1.000000" hp="1" damage="1d1" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noblock="yes">
     <ai splitsize="20000" moverandom="yes"/>
     <attack type="1" damage="1d1"/>
   </race>
-  <race name="seaserpent" magres="50" maxaura="1.000000" regaura="1.000000" weight="20000" capacity="5000" speed="1.000000" hp="600" ac="3" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" scarepeasants="yes" swim="yes" teach="no" getitem="yes" resistbash="yes" unarmedguard="yes">
+  <race name="seaserpent" magres="50" maxaura="1.000000" regaura="1.000000" weight="20000" capacity="5000" speed="1.000000" hp="600" ac="3" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" scarepeasants="yes" swim="yes" canteach="no" getitem="yes" resistbash="yes" unarmedguard="yes">
     <ai splitsize="6" killpeasants="yes" moverandom="yes" learn="yes" moveattack="yes"/>
     <skill name="tactics" modifier="4"/>
     <attack type="4" damage="1d30"/>
@@ -1203,7 +1202,7 @@
     <familiar race="wolf"/>
     <familiar race="demon"/>
   </race>
-  <race name="shadowdragon" magres="95" maxaura="1.000000" regaura="3.000000" weight="100" capacity="100000" speed="1.000000" hp="2700" ac="10" damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="12" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes">
+  <race name="shadowdragon" magres="95" maxaura="1.000000" regaura="3.000000" weight="100" capacity="100000" speed="1.000000" hp="2700" ac="10" damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="12" scarepeasants="yes" fly="yes" walk="yes" canteach="no" getitem="yes" resistbash="yes">
     <ai splitsize="1" killpeasants="yes" learn="yes"/>
     <skill name="tactics" modifier="20"/>
     <skill name="perception" modifier="20"/>
diff --git a/res/races/dragon.xml b/res/races/dragon.xml
index 7e0da2056..c9692cd9b 100644
--- a/res/races/dragon.xml
+++ b/res/races/dragon.xml
@@ -3,7 +3,7 @@
 <race name="dragon" magres="70" maxaura="1.0" regaura="2.000000" weight="10000" capacity="1000000" speed="1.500000" hp="900" ac=
 "6" damage="2d30" unarmedattack="0" unarmeddefense="0"
 attackmodifier="7" defensemodifier="7" scarepeasants="yes" fly="yes"
-income="1000" walk="yes" teach="no" getitem="yes" resistbash="yes"
+income="1000" walk="yes" canteach="no" getitem="yes" resistbash="yes"
 dragon="yes">
   <ai splitsize="2" killpeasants="yes" learn="yes" scare="400"/>
   <function name="name" value="namedragon"/>
diff --git a/res/races/goblin-3.xml b/res/races/goblin-3.xml
index 636f8cc29..9eb7ea835 100644
--- a/res/races/goblin-3.xml
+++ b/res/races/goblin-3.xml
@@ -7,7 +7,7 @@ speed="1.0" hp="16" damage="1d5" unarmedattack="-2" unarmeddefense="0"
 playerrace="yes" walk="yes" giveperson="yes" giveunit="yes"
 getitem="yes" equipment="yes" healing="2.0">
   <ai splitsize="10000" moverandom="yes" learn="yes"/>
-  <param name="hunger.damage" value="1d8+7"/>
+  <param name="hunger_damage" value="1d8+7"/>
   <param name="other_race" value="demon"/>
   <param name="recruit_multi" value="0.5"/>
   <skill name="cartmaking" modifier="-1"/>
diff --git a/res/races/halfling.xml b/res/races/halfling.xml
index 3628d2b35..1f326056f 100644
--- a/res/races/halfling.xml
+++ b/res/races/halfling.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" ?>
 <race name="halfling" magres="5" maxaura="1.000000" regaura="1.000000" recruitcost="80" maintenance="10" weight="1000" capacity="540" speed="1.000000" hp="18" damage="1d5" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" giveperson="yes" giveunit="yes" getitem="yes" equipment="yes">
     <ai splitsize="10000" moverandom="yes" learn="yes"/>
-    <param name="hunger.damage" value="1d14+14"/>
+    <param name="hunger_damage" value="1d14+14"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="mining" modifier="1"/>
     <skill name="bow" modifier="-1"/>
diff --git a/src/exparse.c b/src/exparse.c
index bc7218383..44455888a 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -128,7 +128,19 @@ static void handle_bad_input(parseinfo *pi, const XML_Char *el, const XML_Char *
 static bool handle_flag(int *flags, const XML_Char **pair, const char *names[]) {
     int i;
     for (i = 0; names[i]; ++i) {
-        if (xml_strcmp(pair[0], names[i]) == 0) {
+        const char * name = names[i];
+        if (name[0] == '!') {
+            if (xml_strcmp(pair[0], name+1) == 0) {
+                if (xml_bool(pair[1])) {
+                    *flags &= ~(1 << i);
+                }
+                else {
+                    *flags |= (1 << i);
+                }
+                return true;
+            }
+        }
+        else if (xml_strcmp(pair[0], name) == 0) {
             if (xml_bool(pair[1])) {
                 *flags |= (1 << i);
             }
@@ -865,6 +877,173 @@ static void XMLCALL start_ships(parseinfo *pi, const XML_Char *el, const XML_Cha
     }
 }
 
+static void XMLCALL start_races(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    race *rc = (race *)pi->object;
+    const char *flag_names[] = {
+        "!playerrace", "killpeasants", "scarepeasants", "!cansteal",
+        "moverandom", "cannotmove", "learn", "fly", "swim", "walk",
+        "!canlearn", "!canteach", "horse", "desert", "illusionary",
+        "absorbpeasants", "noheal", "noweapons", "shapeshift",
+        "shapeshiftany", "undead", "dragon", "coastal", "unarmedguard",
+        "cansail", "invisible", "shipspeed", "moveattack", "migrants", NULL };
+    const char *bflag_names[] = {
+        "equipment", "noblock", "resistpierce", "resistcut", "resistbash",
+        "invinciblenonmagic", "noattack", NULL };
+    const char *eflag_names[] = {
+        "giveperson", "giveunit", "getitem", "recruitethereal", 
+        "recruitunlimited", "stonegolem", "irongolem", NULL };
+
+    if (xml_strcmp(el, "attack") == 0) {
+        assert(rc);
+    }
+    else if (xml_strcmp(el, "familiar") == 0) {
+        assert(rc);
+    }
+    else if (xml_strcmp(el, "skill") == 0) {
+        const XML_Char *name = NULL;
+        int i, speed = 0, mod = 0;
+
+        for (i = 0; attr[i]; i += 2) {
+            const XML_Char *key = attr[i], *val = attr[i + 1];
+            if (xml_strcmp(key, "name") == 0) {
+                name = val;
+            }
+            else if (xml_strcmp(key, "modifier") == 0) {
+                mod = xml_int(val);
+            }
+            else if (xml_strcmp(key, "speed") == 0) {
+                speed = xml_int(val);
+            }
+            else {
+                handle_bad_input(pi, el, key);
+            }
+        }
+        if (name) {
+            skill_t sk = findskill(name);
+            if (sk != NOSKILL) {
+                rc->bonus[sk] = (char)mod;
+                if (speed != 0) {
+                    set_study_speed(rc, sk, speed);
+                }
+            }
+        }
+    }
+    else if (xml_strcmp(el, "param") == 0) {
+        const XML_Char *key = attr_get(attr, "name"), *val = attr_get(attr, "value");
+        if (key && val) {
+            rc_set_param(rc, key, val);
+        }
+    }
+    else if (xml_strcmp(el, "ai") == 0) {
+        /* AI flags are cumulative to race flags. XML format is dumb */
+        int i, flags = 0;
+        assert(rc);
+        for (i = 0; attr[i]; i += 2) {
+            const XML_Char *key = attr[i], *val = attr[i + 1];
+            if (xml_strcmp(key, "splitsize") == 0) {
+                rc->splitsize = xml_int(val);
+            }
+            else if (xml_strcmp(key, "scare") == 0) {
+                rc_set_param(rc, "scare", val);
+            }
+            else if (!handle_flag(&flags, attr + i, flag_names)) {
+                handle_bad_input(pi, el, key);
+            }
+        }
+        rc->flags |= flags;
+    }
+    else if (xml_strcmp(el, "race") == 0) {
+        const XML_Char *name;
+
+        name = attr_get(attr, "name");
+        if (name) {
+            assert(!rc);
+            pi->object = rc = rc_get_or_create(name);
+            int i;
+
+            for (i = 0; attr[i]; i += 2) {
+                const XML_Char *key = attr[i], *val = attr[i + 1];
+                if (xml_strcmp(key, "maxaura") == 0) {
+                    rc->maxaura = (int)(100 * xml_float(val));
+                }
+                else if (xml_strcmp(key, "magres") == 0) {
+                    /* specified in percent: */
+                    rc->magres = frac_make(xml_int(val), 100);
+                }
+                else if (xml_strcmp(key, "healing") == 0) {
+                    rc->healing = (int)(xml_float(val) * 100);
+                }
+                else if (xml_strcmp(key, "regaura") == 0) {
+                    rc->regaura = xml_float(val);
+                }
+                else if (xml_strcmp(key, "recruitcost") == 0) {
+                    rc->recruitcost = xml_int(val);
+                }
+                else if (xml_strcmp(key, "maintenance") == 0) {
+                    rc->maintenance = xml_int(val);
+                }
+                else if (xml_strcmp(key, "income") == 0) {
+                    rc->income = xml_int(val);
+                }
+                else if (xml_strcmp(key, "weight") == 0) {
+                    rc->weight = xml_int(val);
+                }
+                else if (xml_strcmp(key, "capacity") == 0) {
+                    rc->capacity = xml_int(val);
+                }
+                else if (xml_strcmp(key, "speed") == 0) {
+                    rc->speed = xml_float(val);
+                }
+                else if (xml_strcmp(key, "hp") == 0) {
+                    rc->hitpoints = xml_int(val);
+                }
+                else if (xml_strcmp(key, "ac") == 0) {
+                    rc->armor = xml_int(val);
+                }
+                else if (xml_strcmp(key, "damage") == 0) {
+                    rc->def_damage = str_strdup(val);
+                }
+                else if (xml_strcmp(key, "unarmedattack") == 0) {
+                    rc->at_default = xml_int(val);
+                }
+                else if (xml_strcmp(key, "unarmeddefense") == 0) {
+                    rc->df_default = xml_int(val);
+                }
+                else if (xml_strcmp(key, "attackmodifier") == 0) {
+                    rc->at_bonus = xml_int(val);
+                }
+                else if (xml_strcmp(key, "defensemodifier") == 0) {
+                    rc->df_bonus = xml_int(val);
+                }
+                else if (xml_strcmp(key, "studyspeed") == 0) {
+                    int study_speed = xml_int(val);
+                    if (study_speed != 0) {
+                        skill_t sk;
+                        for (sk = 0; sk < MAXSKILLS; ++sk) {
+                            set_study_speed(rc, sk, study_speed);
+                        }
+                    }
+
+                }
+                else if (!handle_flag(&rc->flags, attr + i, flag_names)) {
+                    if (!handle_flag(&rc->battle_flags, attr + i, bflag_names)) {
+                        if (!handle_flag(&rc->ec_flags, attr + i, eflag_names)) {
+                            /* we already handled the name earlier: */
+                            if (xml_strcmp(key, "name") != 0) {
+                                handle_bad_input(pi, el, attr[i]);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    else {
+        assert(rc);
+        handle_bad_input(pi, el, NULL);
+    }
+}
+
 static void XMLCALL start_buildings(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     const char *flag_names[] = { "nodestroy", "nobuild", "unique", "decay", "magic", "namechange", "fort", "oneperturn", NULL };
     if (xml_strcmp(el, "building") == 0) {
@@ -979,6 +1158,9 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
     }
     else {
         switch (pi->type) {
+        case EXP_RACES:
+            start_races(pi, el, attr);
+            break;
         case EXP_BUILDINGS:
             start_buildings(pi, el, attr);
             break;
@@ -1063,6 +1245,15 @@ static void end_resources(parseinfo *pi, const XML_Char *el) {
     }
 }
 
+static void end_races(parseinfo *pi, const XML_Char *el) {
+    if (xml_strcmp(el, "race") == 0) {
+        pi->object = NULL;
+    }
+    else if (xml_strcmp(el, "races") == 0) {
+        pi->type = EXP_UNKNOWN;
+    }
+}
+
 static void end_ships(parseinfo *pi, const XML_Char *el) {
     ship_type *stype = (ship_type *)pi->object;
     if (xml_strcmp(el, "construction") == 0) {
@@ -1135,6 +1326,9 @@ static void XMLCALL handle_end(void *data, const XML_Char *el) {
     parseinfo *pi = (parseinfo *)data;
 
     switch (pi->type) {
+    case EXP_RACES:
+        end_races(pi, el);
+        break;
     case EXP_SHIPS:
         end_ships(pi, el);
         break;
diff --git a/src/kernel/race.c b/src/kernel/race.c
index ac81f7f78..596f1527f 100644
--- a/src/kernel/race.c
+++ b/src/kernel/race.c
@@ -451,6 +451,12 @@ int rc_herb_trade(const struct race *rc)
     return 500;
 }
 
+void set_study_speed(race *rc, skill_t sk, int modifier) {
+    if (!rc->study_speed)
+        rc->study_speed = calloc(1, MAXSKILLS);
+    rc->study_speed[sk] = (char)modifier;
+}
+
 const race *rc_otherrace(const race *rc)
 {
     variant *v = rc_getoption(rc, RCO_OTHER);
@@ -466,18 +472,13 @@ void rc_set_param(struct race *rc, const char *key, const char *value) {
     if (strcmp(key, "recruit_multi") == 0) {
         rc->recruit_multi = atof(value);
     }
-    else if (strcmp(key, "migrants.formula") == 0) {
-        if (value[0] == '1') {
-            rc->flags |= RCF_MIGRANTS;
-        }
-    }
     else if (strcmp(key, "other_race")==0) {
         rc_setoption(rc, RCO_OTHER, value);
     }
-    else if (strcmp(key, "ai.scare")==0) {
+    else if (strcmp(key, "scare")==0) {
         rc_setoption(rc, RCO_SCARE, value);
     }
-    else if (strcmp(key, "hunger.damage")==0) {
+    else if (strcmp(key, "hunger_damage")==0) {
         rc_setoption(rc, RCO_HUNGER, value);
     }
     else if (strcmp(key, "armor.stamina")==0) {
diff --git a/src/kernel/race.h b/src/kernel/race.h
index 7c38eec57..51c99e0f0 100644
--- a/src/kernel/race.h
+++ b/src/kernel/race.h
@@ -129,7 +129,7 @@ extern "C" {
         int weight;
         int capacity;
         int income;
-        float speed;
+        double speed;
         int hitpoints;
         char *def_damage;
         int armor;
@@ -229,9 +229,11 @@ extern "C" {
 #define RCF_CANSAIL        (1<<24)      /* Einheit darf Schiffe betreten */
 #define RCF_INVISIBLE      (1<<25)      /* not visible in any report */
 #define RCF_SHIPSPEED      (1<<26)      /* race gets +1 on shipspeed */
-#define RCF_MIGRANTS       (1<<27)      /* may have migrant units (human bonus) */
-#define RCF_FAMILIAR       (1<<28)      /* may be a familiar */
-#define RCF_ATTACK_MOVED   (1<<29)      /* may attack if it has moved */
+#define RCF_ATTACK_MOVED   (1<<27)      /* may attack if it has moved */
+#define RCF_MIGRANTS       (1<<28)      /* may have migrant units (human bonus) */
+#define RCF_FAMILIAR       (1<<29)      /* may be a familiar */
+
+#define RCF_DEFAULT (RCF_NOSTEAL|RCF_CANSAIL|RCF_NOLEARN)
 
     /* Economic flags */
 #define ECF_GIVEPERSON     (1<<2)   /* �bergibt Personen */
@@ -271,6 +273,7 @@ extern "C" {
     const char *raceprefix(const struct unit *u);
     void register_race_function(race_func, const char *);
 
+    void set_study_speed(struct race *rc, skill_t sk, int modifier);
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/kernel/race.test.c b/src/kernel/race.test.c
index dcbe26e0e..9a118bc74 100644
--- a/src/kernel/race.test.c
+++ b/src/kernel/race.test.c
@@ -113,9 +113,9 @@ static void test_rc_set_param(CuTest *tc) {
     rc_set_param(rc, "migrants.formula", "1");
     CuAssertIntEquals(tc, RCF_MIGRANTS, rc->flags&RCF_MIGRANTS);
     CuAssertIntEquals(tc, MIGRANTS_LOG10, rc_migrants_formula(rc));
-    rc_set_param(rc, "ai.scare", "400");
+    rc_set_param(rc, "scare", "400");
     CuAssertIntEquals(tc, 400, rc_scare(rc));
-    rc_set_param(rc, "hunger.damage", "1d10+12");
+    rc_set_param(rc, "hunger_damage", "1d10+12");
     CuAssertStrEquals(tc, "1d10+12", rc_hungerdamage(rc));
     test_teardown();
 }
diff --git a/src/xmlreader.c b/src/xmlreader.c
index 3fd6c1b7b..b26bff66c 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -1256,7 +1256,7 @@ static void parse_ai(race * rc, xmlNodePtr node)
     
     propValue = xmlGetProp(node, BAD_CAST "scare");
     if (propValue) {
-        rc_set_param(rc, "ai.scare", (const char *)propValue);
+        rc_set_param(rc, "scare", (const char *)propValue);
         xmlFree(propValue);
     }
     rc->splitsize = xml_ivalue(node, "splitsize", 0);
@@ -1270,12 +1270,6 @@ static void parse_ai(race * rc, xmlNodePtr node)
         rc->flags |= RCF_ATTACK_MOVED;
 }
 
-static void set_study_speed(race *rc, skill_t sk, int modifier) {
-    if (!rc->study_speed)
-        rc->study_speed = calloc(1, MAXSKILLS);
-    rc->study_speed[sk] = (char)modifier;
-}
-
 static int parse_races(xmlDocPtr doc)
 {
     xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
@@ -1319,7 +1313,7 @@ static int parse_races(xmlDocPtr doc)
             rc->income = xml_ivalue(node, "income", rc->income);
             rc->speed = (float)xml_fvalue(node, "speed", rc->speed);
             rc->hitpoints = xml_ivalue(node, "hp", rc->hitpoints);
-            rc->armor = (char)xml_ivalue(node, "ac", rc->armor);
+            rc->armor = xml_ivalue(node, "ac", rc->armor);
             study_speed_base = xml_ivalue(node, "studyspeed", 0);
             if (study_speed_base != 0) {
                 for (sk = 0; sk < MAXSKILLS; ++sk) {
@@ -1332,14 +1326,18 @@ static int parse_races(xmlDocPtr doc)
             rc->at_bonus = (char)xml_ivalue(node, "attackmodifier", rc->at_bonus);
             rc->df_bonus = (char)xml_ivalue(node, "defensemodifier", rc->df_bonus);
 
+            if (!xml_bvalue(node, "canteach", true))
+                rc->flags |= RCF_NOTEACH;
+            if (!xml_bvalue(node, "cansteal", true))
+                rc->flags |= RCF_NOSTEAL;
+            if (!xml_bvalue(node, "canlearn", true))
+                rc->flags |= RCF_NOLEARN;
             if (!xml_bvalue(node, "playerrace", false)) {
                 assert(rc->recruitcost == 0);
                 rc->flags |= RCF_NPC;
             }
             if (xml_bvalue(node, "scarepeasants", false))
                 rc->flags |= RCF_SCAREPEASANTS;
-            if (!xml_bvalue(node, "cansteal", true))
-                rc->flags |= RCF_NOSTEAL;
             if (xml_bvalue(node, "cansail", true))
                 rc->flags |= RCF_CANSAIL;
             if (xml_bvalue(node, "cannotmove", false))
@@ -1356,10 +1354,6 @@ static int parse_races(xmlDocPtr doc)
                 rc->flags |= RCF_SWIM;
             if (xml_bvalue(node, "walk", false))
                 rc->flags |= RCF_WALK;
-            if (!xml_bvalue(node, "canlearn", true))
-                rc->flags |= RCF_NOLEARN;
-            if (!xml_bvalue(node, "canteach", true))
-                rc->flags |= RCF_NOTEACH;
             if (xml_bvalue(node, "horse", false))
                 rc->flags |= RCF_HORSE;
             if (xml_bvalue(node, "desert", false))

From 48a4de0768df37545e5efc41827fe5797e4cde16 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Thu, 10 May 2018 07:01:46 +0200
Subject: [PATCH 43/59] parse race/attack data

---
 src/exparse.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/src/exparse.c b/src/exparse.c
index 44455888a..e266d55ce 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -877,6 +877,8 @@ static void XMLCALL start_ships(parseinfo *pi, const XML_Char *el, const XML_Cha
     }
 }
 
+static int nattacks;
+
 static void XMLCALL start_races(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     race *rc = (race *)pi->object;
     const char *flag_names[] = {
@@ -894,7 +896,33 @@ static void XMLCALL start_races(parseinfo *pi, const XML_Char *el, const XML_Cha
         "recruitunlimited", "stonegolem", "irongolem", NULL };
 
     if (xml_strcmp(el, "attack") == 0) {
+        int i;
+        struct att * at;
         assert(rc);
+        at = rc->attack + nattacks;
+        at->type = AT_NONE;
+        ++nattacks;
+        if (nattacks >= RACE_ATTACKS) {
+            log_fatal("too many attacks for race '%s'\n", rc->_name);
+        }
+        for (i = 0; attr[i]; i += 2) {
+            const XML_Char *key = attr[i], *val = attr[i + 1];
+            if (xml_strcmp(key, "type") == 0) {
+                at->type = xml_int(val);
+            }
+            else if (xml_strcmp(key, "flags") == 0) {
+                at->flags = xml_int(val);
+            }
+            else if (xml_strcmp(key, "level") == 0) {
+                at->level = xml_int(val);
+            }
+            else if (xml_strcmp(key, "damage") == 0) {
+                at->data.dice = str_strdup(val);
+            }
+            else if (xml_strcmp(key, "spell") == 0) {
+                at->data.sp = spellref_create(NULL, val);
+            }
+        }
     }
     else if (xml_strcmp(el, "familiar") == 0) {
         assert(rc);
@@ -1246,7 +1274,11 @@ static void end_resources(parseinfo *pi, const XML_Char *el) {
 }
 
 static void end_races(parseinfo *pi, const XML_Char *el) {
+    race *rc = (race *)pi->object;
     if (xml_strcmp(el, "race") == 0) {
+        assert(rc);
+        rc->attack[nattacks].type = AT_NONE;
+        nattacks = 0;
         pi->object = NULL;
     }
     else if (xml_strcmp(el, "races") == 0) {

From 85cf8da383e3c229a39921b9c6292b7d09cf8f93 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Thu, 10 May 2018 20:37:37 +0200
Subject: [PATCH 44/59] rename canteach/canlearn to teach/learn race/function
 is never used (and there is no namedragon function).

---
 res/e3a/races.xml         | 78 ++++++++++++++++----------------
 res/eressea/races.xml     | 94 +++++++++++++++++++--------------------
 res/races/dragon.xml      |  3 +-
 res/races/wyrm.xml        |  1 -
 res/races/youngdragon.xml |  1 -
 src/exparse.c             | 34 +++++++++++++-
 src/xmlreader.c           |  6 +--
 7 files changed, 123 insertions(+), 94 deletions(-)

diff --git a/res/e3a/races.xml b/res/e3a/races.xml
index 07322d521..2fa889160 100644
--- a/res/e3a/races.xml
+++ b/res/e3a/races.xml
@@ -8,7 +8,7 @@
     <ai splitsize="10000" moverandom="yes" learn="yes"/>
     <attack type="1" damage="1d4"/>
   </race>
-  <race name="lynx" maxaura="0" regaura="0" weight="500" capacity="540" speed="1.0" hp="20" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="5" walk="yes" canteach="no" getitem="yes">
+  <race name="lynx" maxaura="0" regaura="0" weight="500" capacity="540" speed="1.0" hp="20" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="5" walk="yes" teach="no" getitem="yes">
     <ai splitsize="99999"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -192,7 +192,7 @@
 
   <!-- end player races -->
 
-  <race name="kraken" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="300" damage="2d10" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" coastal="yes" swim="yes" canteach="no" getitem="yes">
+  <race name="kraken" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="300" damage="2d10" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" coastal="yes" swim="yes" teach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -218,7 +218,7 @@
     <attack type="4" damage="1d10"/>
     <attack type="4" damage="1d10"/>
   </race>
-  <race name="giantturtle" maxaura="0.000000" regaura="0.000000" weight="1600" capacity="600" speed="1.0" hp="900" ac="7" damage="2d50" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="5" coastal="yes" swim="yes" walk="yes" canteach="no" getitem="yes">
+  <race name="giantturtle" maxaura="0.000000" regaura="0.000000" weight="1600" capacity="600" speed="1.0" hp="900" ac="7" damage="2d50" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="5" coastal="yes" swim="yes" walk="yes" teach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -239,7 +239,7 @@
     <skill name="cartmaking" modifier="-99"/>
     <attack type="4" damage="2d50"/>
   </race>
-  <race name="dolphin" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="24" damage="1d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="5" coastal="yes" swim="yes" canteach="no" getitem="yes">
+  <race name="dolphin" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="24" damage="1d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="5" coastal="yes" swim="yes" teach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -260,7 +260,7 @@
     <skill name="cartmaking" modifier="-99"/>
     <attack type="4" damage="1d6"/>
   </race>
-  <race name="tiger" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="30" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" walk="yes" canteach="no" getitem="yes">
+  <race name="tiger" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="30" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" walk="yes" teach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -283,7 +283,7 @@
     <attack type="4" damage="1d6"/>
     <attack type="4" damage="1d6"/>
   </race>
-  <race name="hellcat" magres="50" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="40" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" canteach="no" getitem="yes" resistpierce="yes">
+  <race name="hellcat" magres="50" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="40" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" teach="no" getitem="yes" resistpierce="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -306,7 +306,7 @@
     <attack type="4" damage="1d6"/>
     <attack type="4" damage="1d6"/>
   </race>
-  <race name="owl" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="9" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="2" defensemodifier="4" fly="yes" walk="yes" canteach="no" getitem="yes">
+  <race name="owl" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="9" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="2" defensemodifier="4" fly="yes" walk="yes" teach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -328,7 +328,7 @@
     <skill name="cartmaking" modifier="-99"/>
     <attack type="4" damage="1d4"/>
   </race>
-  <race name="fairy" magres="80" maxaura="1.0" regaura="1.500000" weight="200" capacity="540" speed="1.0" hp="6" damage="1d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="14" fly="yes" walk="yes" canteach="no" getitem="yes" equipment="yes">
+  <race name="fairy" magres="80" maxaura="1.0" regaura="1.500000" weight="200" capacity="540" speed="1.0" hp="6" damage="1d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="14" fly="yes" walk="yes" teach="no" getitem="yes" equipment="yes">
     <ai splitsize="5000"/>
     <skill name="magic" modifier="1"/>
     <skill name="riding" modifier="-1"/>
@@ -354,7 +354,7 @@
     <attack type="4" damage="1d3"/>
     <attack type="4" damage="1d3"/>
   </race>
-  <race name="dreamcat" magres="50" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="10" damage="1d5" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="6" fly="yes" walk="yes" canteach="no" getitem="yes" invinciblenonmagic="yes">
+  <race name="dreamcat" magres="50" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="10" damage="1d5" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="6" fly="yes" walk="yes" teach="no" getitem="yes" invinciblenonmagic="yes">
     <ai splitsize="5000"/>
     <skill name="magic" modifier="1"/>
     <skill name="crossbow" modifier="-99"/>
@@ -376,7 +376,7 @@
     <attack type="4" damage="1d5"/>
     <attack type="4" damage="1d5"/>
   </race>
-  <race name="imp" magres="50" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="10" ac="1" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="4" fly="yes" walk="yes" canteach="no" getitem="yes" equipment="yes">
+  <race name="imp" magres="50" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="10" ac="1" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="4" fly="yes" walk="yes" teach="no" getitem="yes" equipment="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -400,7 +400,7 @@
     <attack type="1" damage="1d4"/>
     <attack type="6" spell="fiery_dragonbreath" level="3" />
   </race>
-  <race name="ghost" magres="80" maxaura="0.500000" regaura="0.100000" weight="500" capacity="540" speed="1.0" hp="30" ac="5" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="8" scarepeasants="yes" fly="yes" walk="yes" canteach="no" getitem="yes" equipment="yes" invinciblenonmagic="yes">
+  <race name="ghost" magres="80" maxaura="0.500000" regaura="0.100000" weight="500" capacity="540" speed="1.0" hp="30" ac="5" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="8" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" equipment="yes" invinciblenonmagic="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -425,7 +425,7 @@
     <attack type="2" damage="2d30"/>
     <attack type="3" damage="1d1"/>
   </race>
-  <race name="wolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="25" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" scarepeasants="yes" walk="yes" canteach="no" getitem="yes">
+  <race name="wolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="25" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" scarepeasants="yes" walk="yes" teach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -448,7 +448,7 @@
     <attack type="4" damage="1d4"/>
     <attack type="4" damage="1d4"/>
   </race>
-  <race name="unicorn" magres="90" maxaura="1.500000" regaura="1.500000" weight="5000" capacity="2000" speed="2.000000" hp="40" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" canteach="no" getitem="yes">
+  <race name="unicorn" magres="90" maxaura="1.500000" regaura="1.500000" weight="5000" capacity="2000" speed="2.000000" hp="40" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" teach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -471,7 +471,7 @@
     <attack type="4" damage="3d12"/>
     <attack type="4" damage="2d4"/>
   </race>
-  <race name="nymph" magres="90" maxaura="1.0" regaura="1.500000" weight="1000" capacity="540" speed="1.0" hp="15" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" canteach="no" getitem="yes" equipment="yes">
+  <race name="nymph" magres="90" maxaura="1.0" regaura="1.500000" weight="1000" capacity="540" speed="1.0" hp="15" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" teach="no" getitem="yes" equipment="yes">
     <ai splitsize="9999"/>
     <skill name="mining" modifier="-99"/>
     <skill name="bow" modifier="2"/>
@@ -493,7 +493,7 @@
     <attack type="1" damage="1d4"/>
     <attack type="2" damage="2d20"/>
   </race>
-  <race name="songdragon" magres="99" maxaura="1.0" regaura="1.0" weight="1000" capacity="600" speed="1.500000" hp="40" ac="1" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" fly="yes" walk="yes" canteach="no" getitem="yes">
+  <race name="songdragon" magres="99" maxaura="1.0" regaura="1.0" weight="1000" capacity="600" speed="1.500000" hp="40" ac="1" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" fly="yes" walk="yes" teach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -520,7 +520,7 @@
     <attack type="6" spell="fiery_dragonbreath" level="3" />
   </race>
 
-  <race name="rat" maxaura="0.000000" regaura="0.000000" weight="100" capacity="540" speed="1.0" hp="10" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" walk="yes" canteach="no" getitem="yes">
+  <race name="rat" maxaura="0.000000" regaura="0.000000" weight="100" capacity="540" speed="1.0" hp="10" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" walk="yes" teach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -543,7 +543,7 @@
     <attack type="4" damage="1d4"/>
     <attack type="4" damage="1d4"/>
   </race>
-  <race name="eagle" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.500000" hp="15" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="2" fly="yes" walk="yes" canteach="no" getitem="yes">
+  <race name="eagle" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.500000" hp="15" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="2" fly="yes" walk="yes" teach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -565,7 +565,7 @@
     <skill name="cartmaking" modifier="-99"/>
     <attack type="4" damage="2d3"/>
   </race>
-  <race name="tunnelworm" magres="80" maxaura="0.000000" regaura="0.000000" weight="30000" capacity="10000" speed="1.0" hp="300" ac="6" damage="3d20" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="1" scarepeasants="yes" walk="yes" canteach="no" getitem="yes">
+  <race name="tunnelworm" magres="80" maxaura="0.000000" regaura="0.000000" weight="30000" capacity="10000" speed="1.0" hp="300" ac="6" damage="3d20" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="1" scarepeasants="yes" walk="yes" teach="no" getitem="yes">
     <ai splitsize="99999"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="10"/>
@@ -589,15 +589,15 @@
     <attack type="4" damage="3d20"/>
     <attack type="8" damage="1d10"/>
   </race>
-  <race name="direwolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="20" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" canteach="no" giveperson="yes">
+  <race name="direwolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.0" hp="20" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" teach="no" giveperson="yes">
     <ai splitsize="5000"/>
     <attack type="4" damage="2d4"/>
   </race>
-  <race name="peasant" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="20" damage="1d6" unarmedattack="0" unarmeddefense="0" cannotmove="yes" canteach="no">
+  <race name="peasant" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="20" damage="1d6" unarmedattack="0" unarmeddefense="0" cannotmove="yes" teach="no">
     <ai splitsize="10000"/>
     <attack type="1" damage="1d6"/>
   </race>
-  <race name="braineater" magres="90" maxaura="1.0" regaura="1.0" weight="100" capacity="540" speed="1.0" hp="20" damage="0d0" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" canteach="no" invinciblenonmagic="yes">
+  <race name="braineater" magres="90" maxaura="1.0" regaura="1.0" weight="100" capacity="540" speed="1.0" hp="20" damage="0d0" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" teach="no" invinciblenonmagic="yes">
     <ai splitsize="500" killpeasants="yes" moverandom="yes" learn="yes"/>
     <attack type="2" damage="3d15"/>
     <attack type="3" damage="1d1"/>
@@ -651,34 +651,34 @@
     <skill name="stamina" modifier="-10"/>
     <attack type="4" damage="1d2"/>
   </race>
-  <race name="mountainguard" unarmedguard="yes" magres="50" maxaura="1.0" regaura="0.500000" weight="10000" capacity="2000" speed="0.000000" hp="1000" ac="12" damage="2d40" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="8" cannotmove="yes" canlearn="no" canteach="no" noweapons="yes">
+  <race name="mountainguard" unarmedguard="yes" magres="50" maxaura="1.0" regaura="0.500000" weight="10000" capacity="2000" speed="0.000000" hp="1000" ac="12" damage="2d40" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="8" cannotmove="yes" learn="no" teach="no" noweapons="yes">
     <ai splitsize="1"/>
     <attack type="4" damage="2d40"/>
   </race>
-  <race name="shadowmaster" cansail="no" cansteal="no" canlearn="no" magres="75" maxaura="1.0" regaura="2.000000" weight="500" capacity="540" speed="1.0" hp="150" ac="4" damage="2d5" unarmedattack="0" unarmeddefense="0" attackmodifier="11" defensemodifier="13" scarepeasants="yes" walk="yes" canteach="no" desert="yes">
+  <race name="shadowmaster" cansail="no" cansteal="no" learn="no" magres="75" maxaura="1.0" regaura="2.000000" weight="500" capacity="540" speed="1.0" hp="150" ac="4" damage="2d5" unarmedattack="0" unarmeddefense="0" attackmodifier="11" defensemodifier="13" scarepeasants="yes" walk="yes" teach="no" desert="yes">
     <ai splitsize="50" killpeasants="yes" moverandom="yes" learn="yes"/>
     <attack type="4" damage="2d4"/>
     <attack type="2" damage="2d30"/>
     <attack type="3" damage="1d2"/>
   </race>
-  <race name="shadowdemon" cansail="no" cansteal="no" canlearn="no" magres="75" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="50" ac="3" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="8" defensemodifier="11" scarepeasants="yes" walk="yes" canteach="no" desert="yes" recruitethereal="yes">
+  <race name="shadowdemon" cansail="no" cansteal="no" learn="no" magres="75" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="50" ac="3" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="8" defensemodifier="11" scarepeasants="yes" walk="yes" teach="no" desert="yes" recruitethereal="yes">
     <ai splitsize="1000" killpeasants="yes" moverandom="yes" learn="yes"/>
     <attack type="4" damage="2d3"/>
     <attack type="3" damage="1d1"/>
   </race>
-  <race name="stonegolem" stonegolem="true" magres="25" maxaura="1.0" regaura="0.100000" weight="10000" capacity="2000" speed="1.0" hp="60" ac="4" damage="2d12+6" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" canlearn="no" canteach="no">
+  <race name="stonegolem" stonegolem="true" magres="25" maxaura="1.0" regaura="0.100000" weight="10000" capacity="2000" speed="1.0" hp="60" ac="4" damage="2d12+6" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" learn="no" teach="no">
     <ai splitsize="50"/>
     <skill name="building" modifier="14"/>
     <skill name="roadwork" modifier="14"/>
     <attack type="4" damage="2d10+4"/>
   </race>
-  <race name="irongolem" irongolem="true" magres="25" maxaura="1.0" regaura="0.100000" weight="10000" capacity="2000" speed="1.0" hp="50" ac="2" damage="2d10+4" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" canlearn="no" canteach="no">
+  <race name="irongolem" irongolem="true" magres="25" maxaura="1.0" regaura="0.100000" weight="10000" capacity="2000" speed="1.0" hp="50" ac="2" damage="2d10+4" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" learn="no" teach="no">
     <ai splitsize="50"/>
     <skill name="armorer" modifier="14"/>
     <skill name="weaponsmithing" modifier="14"/>
     <attack type="4" damage="2d8+4"/>
   </race>
-  <race name="spell" maxaura="1" regaura="0.100000" weight="0" capacity="0" speed="0.000000" hp="1" damage="1d4" unarmedattack="-2" unarmeddefense="-2" canlearn="no" noheal="yes" noweapons="yes" illusionary="yes" invisible="yes" fly="yes" swim="yes" walk="yes">
+  <race name="spell" maxaura="1" regaura="0.100000" weight="0" capacity="0" speed="0.000000" hp="1" damage="1d4" unarmedattack="-2" unarmeddefense="-2" learn="no" noheal="yes" noweapons="yes" illusionary="yes" invisible="yes" fly="yes" swim="yes" walk="yes">
     <ai splitsize="1"/>
     <attack type="1" damage="1d4"/>
   </race>
@@ -687,14 +687,14 @@
     <attack type="1" damage="1d4"/>
   </race>
 
-  <race name="dracoid" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="24" damage="1d5" unarmedattack="-2" unarmeddefense="-2" walk="yes" canteach="no" giveperson="yes" getitem="yes" equipment="yes">
+  <race name="dracoid" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="24" damage="1d5" unarmedattack="-2" unarmeddefense="-2" walk="yes" teach="no" giveperson="yes" getitem="yes" equipment="yes">
     <ai splitsize="10000" moverandom="yes" learn="yes"/>
     <attack type="4" damage="1d6"/>
     <attack type="4" damage="1d6"/>
     <attack type="1" damage="1d5"/>
   </race>
 
-  <race name="ent" magres="25" maxaura="1.0" regaura="0.500000" weight="5000" capacity="2500" speed="1.0" hp="50" ac="4" damage="2d4+12" unarmedattack="0" unarmeddefense="0" attackmodifier="9" defensemodifier="7" scarepeasants="yes" walk="yes" canteach="no">
+  <race name="ent" magres="25" maxaura="1.0" regaura="0.500000" weight="5000" capacity="2500" speed="1.0" hp="50" ac="4" damage="2d4+12" unarmedattack="0" unarmeddefense="0" attackmodifier="9" defensemodifier="7" scarepeasants="yes" walk="yes" teach="no">
     <ai splitsize="1000" moverandom="yes" learn="yes"/>
     <attack type="4" damage="2d12"/>
     <attack type="4" damage="2d12"/>
@@ -703,14 +703,14 @@
   <race name="undead" maxaura="1" regaura="1" weight="1000"
   capacity="540" speed="1.0" hp="20" damage="1d7" unarmedattack="0"
   unarmeddefense="0" attackmodifier="1" defensemodifier="1"
-  scarepeasants="yes" walk="yes" canlearn="no" cancanteach="no" noheal="yes"
+  scarepeasants="yes" walk="yes" learn="no" teach="no" noheal="yes"
   undead="yes" equipment="yes" giveperson="yes">
     <ai splitsize="20000" moverandom="yes"/>
     <attack type="4" damage="1d7"/>
     <attack type="5"/>
   </race>
 
-  <race name="clone" magres="90" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.0" hp="40" damage="0d0" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" canlearn="no" canteach="no" noheal="yes">
+  <race name="clone" magres="90" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.0" hp="40" damage="0d0" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" learn="no" teach="no" noheal="yes">
     <ai splitsize="10000"/>
     <skill name="crossbow" modifier="-99"/>
     <skill name="mining" modifier="-99"/>
@@ -736,7 +736,7 @@
     <attack type="1" damage="0d0"/>
   </race>
 
-  <race name="ghast" magres="60" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="60" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
+  <race name="ghast" magres="60" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="60" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" learn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
     <ai splitsize="2000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -754,7 +754,7 @@
     <attack type="2" damage="1d30"/>
   </race>
 
-  <race name="ghoul" magres="30" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="30" ac="1" damage="1d7" unarmedattack="3" unarmeddefense="3" attackmodifier="3" defensemodifier="3" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
+  <race name="ghoul" magres="30" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="30" ac="1" damage="1d7" unarmedattack="3" unarmeddefense="3" attackmodifier="3" defensemodifier="3" scarepeasants="yes" walk="yes" learn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
     <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -771,7 +771,7 @@
     <attack type="2" damage="1d30"/>
   </race>
 
-  <race name="juju" magres="50" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="80" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistbash="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="juju" magres="50" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="80" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" learn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistbash="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="2000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -787,7 +787,7 @@
     <attack type="3" damage="1d1"/>
   </race>
 
-  <race name="zombie" magres="20" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="40" ac="1" damage="1d7" unarmedattack="2" unarmeddefense="2" attackmodifier="5" defensemodifier="5" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="zombie" magres="20" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="40" ac="1" damage="1d7" unarmedattack="2" unarmeddefense="2" attackmodifier="5" defensemodifier="5" scarepeasants="yes" walk="yes" learn="no" teach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -801,7 +801,7 @@
     <attack type="1" damage="1d7"/>
   </race>
 
-  <race name="skeletonlord" magres="30" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="60" ac="4" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="skeletonlord" magres="30" maxaura="1.0" regaura="1.0" weight="1000" capacity="540" speed="1.0" hp="60" ac="4" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" learn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="2000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -816,7 +816,7 @@
     <attack type="1" damage="1d7"/>
   </race>
 
-  <race name="skeleton" magres="10" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="20" ac="1" damage="1d7" unarmedattack="1" unarmeddefense="1" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="skeleton" magres="10" maxaura="1.0" regaura="1.0" weight="500" capacity="540" speed="1.0" hp="20" ac="1" damage="1d7" unarmedattack="1" unarmeddefense="1" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" learn="no" teach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -830,12 +830,12 @@
     <attack type="1" damage="1d7"/>
   </race>
 
-  <race name="shadowknight" maxaura="0.000000" regaura="0.000000" weight="0" capacity="540" speed="1.0" hp="1" damage="1d1" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noblock="yes">
+  <race name="shadowknight" maxaura="0.000000" regaura="0.000000" weight="0" capacity="540" speed="1.0" hp="1" damage="1d1" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" walk="yes" learn="no" teach="no" noblock="yes">
     <ai splitsize="20000" moverandom="yes"/>
     <attack type="1" damage="1d1"/>
   </race>
 
-  <race name="seaserpent" magres="50" maxaura="1.0" regaura="1.0" weight="20000" capacity="5000" speed="1.0" hp="600" ac="3" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" scarepeasants="yes" swim="yes" canteach="no" getitem="yes" resistbash="yes">
+  <race name="seaserpent" magres="50" maxaura="1.0" regaura="1.0" weight="20000" capacity="5000" speed="1.0" hp="600" ac="3" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" scarepeasants="yes" swim="yes" teach="no" getitem="yes" resistbash="yes">
     <ai splitsize="6" killpeasants="yes" moverandom="yes" learn="yes" moveattack="yes"/>
     <skill name="tactics" modifier="4"/>
     <attack type="4" damage="1d30"/>
diff --git a/res/eressea/races.xml b/res/eressea/races.xml
index 851d89de6..1acffa872 100644
--- a/res/eressea/races.xml
+++ b/res/eressea/races.xml
@@ -6,7 +6,7 @@
         regaura="0" weight="500" capacity="200" equipment="no"
         speed="1" hp="1000" ac="4" damage="2d4" unarmedattack="10"
         unarmeddefense="10" attackmodifier="8" defensemodifier="8"
-        fly="no" walk="no" canteach="no" getitem="yes">
+        fly="no" walk="no" teach="no" getitem="yes">
     <attack type="4" damage="2d6+2"/>
     <attack type="3" damage="2d6+2"/>
   </race>
@@ -26,7 +26,7 @@
     <familiar race="eagle"/>
     <familiar race="imp"/>
   </race>
-  <race name="kraken" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="300" damage="2d10" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" coastal="yes" swim="yes" canteach="no" getitem="yes">
+  <race name="kraken" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="300" damage="2d10" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" coastal="yes" swim="yes" teach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="perception" modifier="1"/>
     <skill name="alchemy" modifier="-99"/>
@@ -59,7 +59,7 @@
     <attack type="4" damage="1d10"/>
     <attack type="4" damage="1d10"/>
   </race>
-  <race name="giantturtle" maxaura="0.000000" regaura="0.000000" weight="1600" capacity="600" speed="1.000000" hp="900" ac="7" damage="2d50" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="5" coastal="yes" swim="yes" walk="yes" canteach="no" getitem="yes">
+  <race name="giantturtle" maxaura="0.000000" regaura="0.000000" weight="1600" capacity="600" speed="1.000000" hp="900" ac="7" damage="2d50" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="5" coastal="yes" swim="yes" walk="yes" teach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="perception" modifier="1"/>
     <skill name="alchemy" modifier="-99"/>
@@ -87,7 +87,7 @@
     <skill name="taxation" modifier="-99"/>
     <attack type="4" damage="2d50"/>
   </race>
-  <race name="dolphin" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="24" damage="1d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="5" coastal="yes" swim="yes" canteach="no" getitem="yes">
+  <race name="dolphin" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="2.000000" hp="24" damage="1d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="5" coastal="yes" swim="yes" teach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -114,7 +114,7 @@
     <skill name="taxation" modifier="-99"/>
     <attack type="4" damage="1d6"/>
   </race>
-  <race name="tiger" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="30" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" walk="yes" canteach="no" getitem="yes">
+  <race name="tiger" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="30" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" walk="yes" teach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -143,7 +143,7 @@
     <attack type="4" damage="1d6"/>
     <attack type="4" damage="1d6"/>
   </race>
-  <race name="hellcat" magres="50" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="40" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" canteach="no" getitem="yes" resistpierce="yes">
+  <race name="hellcat" magres="50" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="40" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" teach="no" getitem="yes" resistpierce="yes">
     <ai splitsize="5000"/>
     <skill name="perception" modifier="1"/>
     <skill name="alchemy" modifier="-99"/>
@@ -172,7 +172,7 @@
     <attack type="4" damage="1d6"/>
     <attack type="4" damage="1d6"/>
   </race>
-  <race name="owl" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="9" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="2" defensemodifier="4" fly="yes" walk="yes" canteach="no" getitem="yes">
+  <race name="owl" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="9" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="2" defensemodifier="4" fly="yes" walk="yes" teach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="espionage" modifier="1"/>
     <skill name="stealth" modifier="1"/>
@@ -202,7 +202,7 @@
     <skill name="taxation" modifier="-99"/>
     <attack type="4" damage="1d4"/>
   </race>
-  <race name="fairy" magres="80" maxaura="1.000000" regaura="1.500000" weight="200" capacity="540" speed="1.000000" hp="6" damage="1d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="14" fly="yes" walk="yes" canteach="no" getitem="yes" equipment="yes">
+  <race name="fairy" magres="80" maxaura="1.000000" regaura="1.500000" weight="200" capacity="540" speed="1.000000" hp="6" damage="1d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="14" fly="yes" walk="yes" teach="no" getitem="yes" equipment="yes">
     <ai splitsize="5000"/>
     <skill name="stealth" modifier="5"/>
     <skill name="espionage" modifier="2"/>
@@ -236,7 +236,7 @@
     <attack type="4" damage="1d3"/>
     <attack type="4" damage="1d3"/>
   </race>
-  <race name="dreamcat" magres="50" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="10" damage="1d5" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="6" fly="yes" walk="yes" canteach="no" getitem="yes" invinciblenonmagic="yes">
+  <race name="dreamcat" magres="50" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="10" damage="1d5" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="6" fly="yes" walk="yes" teach="no" getitem="yes" invinciblenonmagic="yes">
     <ai splitsize="5000"/>
     <skill name="magic" modifier="1"/>
     <skill name="espionage" modifier="1"/>
@@ -266,7 +266,7 @@
     <attack type="4" damage="1d5"/>
     <attack type="4" damage="1d5"/>
   </race>
-  <race name="imp" magres="50" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="10" ac="1" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="4" fly="yes" walk="yes" canteach="no" getitem="yes" equipment="yes">
+  <race name="imp" magres="50" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="10" ac="1" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="4" fly="yes" walk="yes" teach="no" getitem="yes" equipment="yes">
     <ai splitsize="5000"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -298,7 +298,7 @@
     <attack type="1" damage="1d4"/>
     <attack type="6" spell="fiery_dragonbreath" level="3" />
   </race>
-  <race name="ghost" magres="80" maxaura="0.500000" regaura="0.100000" weight="500" capacity="540" speed="1.000000" hp="30" ac="5" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="8" scarepeasants="yes" fly="yes" walk="yes" canteach="no" getitem="yes" equipment="yes" invinciblenonmagic="yes">
+  <race name="ghost" magres="80" maxaura="0.500000" regaura="0.100000" weight="500" capacity="540" speed="1.000000" hp="30" ac="5" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="5" defensemodifier="8" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" equipment="yes" invinciblenonmagic="yes">
     <ai splitsize="5000"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -328,7 +328,7 @@
     <attack type="2" damage="2d30"/>
     <attack type="3" damage="1d1"/>
   </race>
-  <race name="wolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="25" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" scarepeasants="yes" walk="yes" canteach="no" getitem="yes">
+  <race name="wolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="25" damage="2d6" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="3" scarepeasants="yes" walk="yes" teach="no" getitem="yes">
     <ai splitsize="5000"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -357,7 +357,7 @@
     <attack type="4" damage="1d4"/>
     <attack type="4" damage="1d4"/>
   </race>
-  <race name="unicorn" magres="90" maxaura="1.500000" regaura="1.500000" weight="5000" capacity="2000" speed="2.000000" hp="40" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" canteach="no" getitem="yes">
+  <race name="unicorn" magres="90" maxaura="1.500000" regaura="1.500000" weight="5000" capacity="2000" speed="2.000000" hp="40" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="4" walk="yes" teach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -387,7 +387,7 @@
     <attack type="4" damage="3d12"/>
     <attack type="4" damage="2d4"/>
   </race>
-  <race name="nymph" magres="90" maxaura="1.000000" regaura="1.500000" weight="1000" capacity="540" speed="1.000000" hp="15" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" canteach="no" getitem="yes" equipment="yes">
+  <race name="nymph" magres="90" maxaura="1.000000" regaura="1.500000" weight="1000" capacity="540" speed="1.000000" hp="15" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" teach="no" getitem="yes" equipment="yes">
     <ai splitsize="9999"/>
     <skill name="mining" modifier="-99"/>
     <skill name="bow" modifier="2"/>
@@ -416,7 +416,7 @@
     <attack type="1" damage="1d4"/>
     <attack type="2" damage="2d20"/>
   </race>
-  <race name="songdragon" magres="99" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="600" speed="1.500000" hp="40" ac="1" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" fly="yes" walk="yes" canteach="no" getitem="yes" unarmedguard="yes">
+  <race name="songdragon" magres="99" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="600" speed="1.500000" hp="40" ac="1" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" fly="yes" walk="yes" teach="no" getitem="yes" unarmedguard="yes">
     <ai splitsize="9999"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -447,7 +447,7 @@
     <attack type="4" damage="2d4"/>
     <attack type="6" spell="fiery_dragonbreath" level="3" />
   </race>
-  <race name="rat" maxaura="0.000000" regaura="0.000000" weight="100" capacity="540" speed="1.000000" hp="10" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" walk="yes" canteach="no" getitem="yes">
+  <race name="rat" maxaura="0.000000" regaura="0.000000" weight="100" capacity="540" speed="1.000000" hp="10" damage="1d4" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" walk="yes" teach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="espionage" modifier="5"/>
     <skill name="stealth" modifier="4"/>
@@ -478,7 +478,7 @@
     <attack type="4" damage="1d4"/>
     <attack type="4" damage="1d4"/>
   </race>
-  <race name="eagle" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.500000" hp="15" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="2" fly="yes" walk="yes" canteach="no" getitem="yes">
+  <race name="eagle" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.500000" hp="15" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="2" fly="yes" walk="yes" teach="no" getitem="yes">
     <ai splitsize="9999"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -507,7 +507,7 @@
     <skill name="taxation" modifier="-99"/>
     <attack type="4" damage="2d3"/>
   </race>
-  <race name="tunnelworm" magres="80" maxaura="0.000000" regaura="0.000000" weight="30000" capacity="10000" speed="1.000000" hp="300" ac="6" damage="3d20" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="1" scarepeasants="yes" walk="yes" canteach="no" getitem="yes">
+  <race name="tunnelworm" magres="80" maxaura="0.000000" regaura="0.000000" weight="30000" capacity="10000" speed="1.000000" hp="300" ac="6" damage="3d20" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="1" scarepeasants="yes" walk="yes" teach="no" getitem="yes">
     <ai splitsize="99999"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -539,7 +539,7 @@
     <attack type="4" damage="3d20"/>
     <attack type="8" damage="1d10"/>
   </race>
-  <race name="lynx" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="20" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="5" walk="yes" canteach="no" getitem="yes">
+  <race name="lynx" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="20" damage="2d3" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="5" walk="yes" teach="no" getitem="yes">
     <ai splitsize="99999"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -569,16 +569,16 @@
     <skill name="taxation" modifier="-99"/>
     <attack type="4" damage="2d3"/>
   </race>
-  <race name="direwolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="20" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" canteach="no" giveperson="yes">
+  <race name="direwolf" maxaura="0.000000" regaura="0.000000" weight="500" capacity="540" speed="1.000000" hp="20" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="1" walk="yes" teach="no" giveperson="yes">
     <ai splitsize="5000"/>
     <attack type="4" damage="2d4"/>
   </race>
-  <race name="peasant" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d6" unarmedattack="0" unarmeddefense="0" cannotmove="yes" canteach="no">
+  <race name="peasant" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d6" unarmedattack="0" unarmeddefense="0" cannotmove="yes" teach="no">
     <ai splitsize="10000"/>
     <attack type="1" damage="1d6"/>
   </race>
   <race name="braineater" magres="90" maxaura="1.000000"
-  regaura="1.000000" weight="100" capacity="540" speed="1.000000" hp="20" damage="0d0" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" canteach="no" invinciblenonmagic="yes">
+  regaura="1.000000" weight="100" capacity="540" speed="1.000000" hp="20" damage="0d0" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" teach="no" invinciblenonmagic="yes">
     <ai splitsize="500" killpeasants="yes" moverandom="yes" learn="yes"/>
     <attack type="2" damage="3d15"/>
     <attack type="3" damage="1d1"/>
@@ -648,34 +648,34 @@
     <skill name="stamina" modifier="-10"/>
     <attack type="4" damage="1d2"/>
   </race>
-  <race name="mountainguard" unarmedguard="yes" magres="50" maxaura="1.000000" regaura="0.500000" weight="10000" capacity="2000" speed="0.000000" hp="1000" ac="12" damage="2d40" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="8" cannotmove="yes" canlearn="no" canteach="no" noweapons="yes">
+  <race name="mountainguard" unarmedguard="yes" magres="50" maxaura="1.000000" regaura="0.500000" weight="10000" capacity="2000" speed="0.000000" hp="1000" ac="12" damage="2d40" unarmedattack="0" unarmeddefense="0" attackmodifier="6" defensemodifier="8" cannotmove="yes" learn="no" teach="no" noweapons="yes">
     <ai splitsize="1"/>
     <attack type="4" damage="2d40"/>
   </race>
-  <race name="shadowmaster" cansail="no" cansteal="no" canlearn="no" magres="75" maxaura="1.000000" regaura="2.000000" weight="500" capacity="540" speed="1.000000" hp="150" ac="4" damage="2d5" unarmedattack="0" unarmeddefense="0" attackmodifier="11" defensemodifier="13" scarepeasants="yes" walk="yes" canteach="no" desert="yes">
+  <race name="shadowmaster" cansail="no" cansteal="no" learn="no" magres="75" maxaura="1.000000" regaura="2.000000" weight="500" capacity="540" speed="1.000000" hp="150" ac="4" damage="2d5" unarmedattack="0" unarmeddefense="0" attackmodifier="11" defensemodifier="13" scarepeasants="yes" walk="yes" teach="no" desert="yes">
     <ai splitsize="50" killpeasants="yes" moverandom="yes" learn="yes"/>
     <attack type="4" damage="2d4"/>
     <attack type="2" damage="2d30"/>
     <attack type="3" damage="1d2"/>
   </race>
-  <race name="shadowdemon" cansail="no" cansteal="no" canlearn="no" magres="75" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="50" ac="3" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="8" defensemodifier="11" scarepeasants="yes" walk="yes" canteach="no" desert="yes" recruitethereal="yes">
+  <race name="shadowdemon" cansail="no" cansteal="no" learn="no" magres="75" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="50" ac="3" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="8" defensemodifier="11" scarepeasants="yes" walk="yes" teach="no" desert="yes" recruitethereal="yes">
     <ai splitsize="1000" killpeasants="yes" moverandom="yes" learn="yes"/>
     <attack type="4" damage="2d3"/>
     <attack type="3" damage="1d1"/>
   </race>
-  <race name="stonegolem" stonegolem="true" magres="25" maxaura="1.000000" regaura="0.100000" weight="10000" capacity="2000" speed="1.000000" hp="60" ac="4" damage="2d12+6" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" canlearn="no" canteach="no">
+  <race name="stonegolem" stonegolem="true" magres="25" maxaura="1.000000" regaura="0.100000" weight="10000" capacity="2000" speed="1.000000" hp="60" ac="4" damage="2d12+6" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" learn="no" teach="no">
     <ai splitsize="50"/>
     <skill name="building" modifier="14"/>
     <skill name="roadwork" modifier="14"/>
     <attack type="4" damage="2d10+4"/>
   </race>
-  <race name="irongolem" irongolem="true" magres="25" maxaura="1.000000" regaura="0.100000" weight="10000" capacity="2000" speed="1.000000" hp="50" ac="2" damage="2d10+4" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" canlearn="no" canteach="no">
+  <race name="irongolem" irongolem="true" magres="25" maxaura="1.000000" regaura="0.100000" weight="10000" capacity="2000" speed="1.000000" hp="50" ac="2" damage="2d10+4" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="2" walk="yes" learn="no" teach="no">
     <ai splitsize="50"/>
     <skill name="armorer" modifier="14"/>
     <skill name="weaponsmithing" modifier="14"/>
     <attack type="4" damage="2d8+4"/>
   </race>
-  <race name="spell" maxaura="1" regaura="0.100000" weight="0" capacity="0" speed="0" hp="1" damage="1d4" unarmedattack="-2" unarmeddefense="-2" canlearn="no" noheal="yes" noweapons="yes" illusionary="yes" invisible="yes" fly="yes" swim="yes" walk="yes">
+  <race name="spell" maxaura="1" regaura="0.100000" weight="0" capacity="0" speed="0" hp="1" damage="1d4" unarmedattack="-2" unarmeddefense="-2" learn="no" noheal="yes" noweapons="yes" illusionary="yes" invisible="yes" fly="yes" swim="yes" walk="yes">
     <ai splitsize="1"/>
     <attack type="1" damage="1d4"/>
   </race>
@@ -683,25 +683,25 @@
     <ai splitsize="1"/>
     <attack type="1" damage="1d4"/>
   </race>
-  <race name="dracoid" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="24" damage="1d5" unarmedattack="-2" unarmeddefense="-2" walk="yes" canteach="no" giveperson="yes" getitem="yes" equipment="yes">
+  <race name="dracoid" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="24" damage="1d5" unarmedattack="-2" unarmeddefense="-2" walk="yes" teach="no" giveperson="yes" getitem="yes" equipment="yes">
     <ai splitsize="10000" moverandom="yes" learn="yes"/>
     <attack type="4" damage="1d6"/>
     <attack type="4" damage="1d6"/>
     <attack type="1" damage="1d5"/>
   </race>
-  <race name="catdragon" magres="90" maxaura="1.000000" regaura="1.000000" weight="20000" capacity="10000" speed="1.000000" hp="20" damage="2d40" unarmedattack="0" unarmeddefense="0" defensemodifier="50" fly="yes" walk="yes" canteach="no" shapeshift="yes" giveperson="yes" getitem="yes" dragon="yes">
+  <race name="catdragon" magres="90" maxaura="1.000000" regaura="1.000000" weight="20000" capacity="10000" speed="1.000000" hp="20" damage="2d40" unarmedattack="0" unarmeddefense="0" defensemodifier="50" fly="yes" walk="yes" teach="no" shapeshift="yes" giveperson="yes" getitem="yes" dragon="yes">
     <ai splitsize="1"/>
     <attack type="4" damage="2d40"/>
     <attack type="4" damage="2d40"/>
     <attack type="4" damage="2d40"/>
     <attack type="4" damage="2d40"/>
   </race>
-  <race name="ent" magres="25" maxaura="1.000000" regaura="0.500000" weight="5000" capacity="2500" speed="1.000000" hp="50" ac="4" damage="2d4+12" unarmedattack="0" unarmeddefense="0" attackmodifier="9" defensemodifier="7" scarepeasants="yes" walk="yes" canteach="no">
+  <race name="ent" magres="25" maxaura="1.000000" regaura="0.500000" weight="5000" capacity="2500" speed="1.000000" hp="50" ac="4" damage="2d4+12" unarmedattack="0" unarmeddefense="0" attackmodifier="9" defensemodifier="7" scarepeasants="yes" walk="yes" teach="no">
     <ai splitsize="1000" moverandom="yes" learn="yes"/>
     <attack type="4" damage="2d12"/>
     <attack type="4" damage="2d12"/>
   </race>
-  <race name="wyrm" magres="90" maxaura="1.000000" regaura="3.000000" weight="18000" capacity="1000000" speed="1.000000" hp="2700" ac="8" damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" canteach="no" getitem="yes" resistbash="yes" dragon="yes" unarmedguard="yes">
+  <race name="wyrm" magres="90" maxaura="1.000000" regaura="3.000000" weight="18000" capacity="1000000" speed="1.000000" hp="2700" ac="8" damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes" dragon="yes" unarmedguard="yes">
     <ai splitsize="1" killpeasants="yes" learn="yes"/>
     <skill name="magic" modifier="12"/>
     <skill name="tactics" modifier="12"/>
@@ -711,7 +711,7 @@
     <attack type="4" damage="5d30"/>
     <attack type="6" spell="powerful_dragonbreath" level="12" />
   </race>
-  <race name="dragon" magres="70" maxaura="1.000000" regaura="2.000000" weight="10000" capacity="1000000" speed="1.500000" hp="900" ac="6" damage="2d30" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" scarepeasants="yes" fly="yes" walk="yes" canteach="no" getitem="yes" resistbash="yes" unarmedguard="yes" dragon="yes">
+  <race name="dragon" magres="70" maxaura="1.000000" regaura="2.000000" weight="10000" capacity="1000000" speed="1.500000" hp="900" ac="6" damage="2d30" unarmedattack="0" unarmeddefense="0" attackmodifier="7" defensemodifier="7" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes" unarmedguard="yes" dragon="yes">
     <ai splitsize="2" killpeasants="yes" learn="yes"/>
     <skill name="magic" modifier="8"/>
     <skill name="tactics" modifier="8"/>
@@ -721,7 +721,7 @@
     <attack type="4" damage="3d30"/>
     <attack type="6" spell="icy_dragonbreath" level="6" />
   </race>
-  <race name="youngdragon" magres="50" maxaura="1.000000" regaura="1.000000" weight="20000" capacity="10000" speed="1.000000" hp="300" ac="4" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" scarepeasants="yes" fly="yes" walk="yes" canteach="no" getitem="yes" resistbash="yes" unarmedguard="yes">
+  <race name="youngdragon" magres="50" maxaura="1.000000" regaura="1.000000" weight="20000" capacity="10000" speed="1.000000" hp="300" ac="4" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes" unarmedguard="yes">
     <ai splitsize="6" killpeasants="yes" learn="yes"/>
     <skill name="magic" modifier="4"/>
     <skill name="tactics" modifier="4"/>
@@ -732,7 +732,7 @@
     <attack type="4" damage="1d30"/>
     <attack type="6" spell="fiery_dragonbreath" level="3" />
   </race>
-  <race name="undead" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d7" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
+  <race name="undead" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="20" damage="1d7" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" walk="yes" learn="no" teach="no" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
     <ai splitsize="20000" moverandom="yes"/>
     <attack type="4" damage="1d7"/>
     <attack type="5"/>
@@ -924,7 +924,7 @@
     <familiar race="rat"/>
     <familiar race="imp"/>
   </race>
-  <race name="clone" magres="90" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.000000" hp="40" damage="0d0" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" canlearn="no" canteach="no" noheal="yes">
+  <race name="clone" magres="90" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.000000" hp="40" damage="0d0" unarmedattack="-2" unarmeddefense="-2" playerrace="yes" walk="yes" learn="no" teach="no" noheal="yes">
     <ai splitsize="10000"/>
     <skill name="alchemy" modifier="-99"/>
     <skill name="crossbow" modifier="-99"/>
@@ -961,7 +961,7 @@
     <ai splitsize="10000" moverandom="yes" learn="yes"/>
     <attack type="1" damage="1d4"/>
   </race>
-  <race name="gnome" magres="100" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.000000" hp="50" damage="1d4" unarmedattack="10" unarmeddefense="10" attackmodifier="10" defensemodifier="10" walk="yes" canteach="no">
+  <race name="gnome" magres="100" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.000000" hp="50" damage="1d4" unarmedattack="10" unarmeddefense="10" attackmodifier="10" defensemodifier="10" walk="yes" teach="no">
     <ai splitsize="10000"/>
     <skill name="tactics" modifier="1"/>
     <skill name="perception" modifier="1"/>
@@ -969,7 +969,7 @@
     <skill name="unarmed" modifier="1"/>
     <attack type="1" damage="1d4"/>
   </race>
-  <race name="museumghost" magres="100" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.000000" hp="50" damage="1d4" unarmedattack="10" unarmeddefense="10" attackmodifier="10" defensemodifier="10" walk="yes" canteach="no">
+  <race name="museumghost" magres="100" maxaura="0.000000" regaura="0.000000" weight="1000" capacity="540" speed="1.000000" hp="50" damage="1d4" unarmedattack="10" unarmeddefense="10" attackmodifier="10" defensemodifier="10" walk="yes" teach="no">
     <ai splitsize="10000"/>
     <skill name="tactics" modifier="1"/>
     <skill name="perception" modifier="1"/>
@@ -983,7 +983,7 @@
     <attack type="2" damage="5d600"/>
     <attack type="1" damage="1d4"/>
   </race>
-  <race name="ghast" magres="60" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="60" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
+  <race name="ghast" magres="60" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="60" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" learn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
     <ai splitsize="2000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -1000,7 +1000,7 @@
     <attack type="2" damage="1d30"/>
     <attack type="2" damage="1d30"/>
   </race>
-  <race name="ghoul" magres="30" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="30" ac="1" damage="1d7" unarmedattack="3" unarmeddefense="3" attackmodifier="3" defensemodifier="3" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
+  <race name="ghoul" magres="30" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="30" ac="1" damage="1d7" unarmedattack="3" unarmeddefense="3" attackmodifier="3" defensemodifier="3" scarepeasants="yes" walk="yes" learn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" giveperson="yes">
     <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -1016,7 +1016,7 @@
     <attack type="3" damage="1d2"/>
     <attack type="2" damage="1d30"/>
   </race>
-  <race name="juju" magres="50" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="80" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistbash="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="juju" magres="50" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="80" ac="2" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" learn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistbash="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="2000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -1031,7 +1031,7 @@
     <attack type="3" damage="1d1"/>
     <attack type="3" damage="1d1"/>
   </race>
-  <race name="zombie" magres="20" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="40" ac="1" damage="1d7" unarmedattack="2" unarmeddefense="2" attackmodifier="5" defensemodifier="5" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="zombie" magres="20" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="40" ac="1" damage="1d7" unarmedattack="2" unarmeddefense="2" attackmodifier="5" defensemodifier="5" scarepeasants="yes" walk="yes" learn="no" teach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -1044,7 +1044,7 @@
     <skill name="unarmed" modifier="1"/>
     <attack type="1" damage="1d7"/>
   </race>
-  <race name="skeletonlord" magres="30" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="60" ac="4" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="skeletonlord" magres="30" maxaura="1.000000" regaura="1.000000" weight="1000" capacity="540" speed="1.000000" hp="60" ac="4" damage="1d7" unarmedattack="6" unarmeddefense="6" attackmodifier="8" defensemodifier="8" scarepeasants="yes" walk="yes" learn="no" teach="no" absorbpeasants="yes" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="2000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -1058,7 +1058,7 @@
     <attack type="1" damage="1d7"/>
     <attack type="1" damage="1d7"/>
   </race>
-  <race name="skeleton" magres="10" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="20" ac="1" damage="1d7" unarmedattack="1" unarmeddefense="1" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
+  <race name="skeleton" magres="10" maxaura="1.000000" regaura="1.000000" weight="500" capacity="540" speed="1.000000" hp="20" ac="1" damage="1d7" unarmedattack="1" unarmeddefense="1" attackmodifier="6" defensemodifier="6" scarepeasants="yes" walk="yes" learn="no" teach="no" noheal="yes" undead="yes" equipment="yes" resistcut="yes" resistpierce="yes" giveperson="yes">
     <ai splitsize="10000" killpeasants="yes" moverandom="yes"/>
     <skill name="crossbow" modifier="1"/>
     <skill name="bow" modifier="1"/>
@@ -1071,11 +1071,11 @@
     <skill name="unarmed" modifier="1"/>
     <attack type="1" damage="1d7"/>
   </race>
-  <race name="shadowknight" maxaura="0.000000" regaura="0.000000" weight="0" capacity="540" speed="1.000000" hp="1" damage="1d1" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" walk="yes" canlearn="no" canteach="no" noblock="yes">
+  <race name="shadowknight" maxaura="0.000000" regaura="0.000000" weight="0" capacity="540" speed="1.000000" hp="1" damage="1d1" unarmedattack="0" unarmeddefense="0" attackmodifier="1" defensemodifier="1" scarepeasants="yes" walk="yes" learn="no" teach="no" noblock="yes">
     <ai splitsize="20000" moverandom="yes"/>
     <attack type="1" damage="1d1"/>
   </race>
-  <race name="seaserpent" magres="50" maxaura="1.000000" regaura="1.000000" weight="20000" capacity="5000" speed="1.000000" hp="600" ac="3" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" scarepeasants="yes" swim="yes" canteach="no" getitem="yes" resistbash="yes" unarmedguard="yes">
+  <race name="seaserpent" magres="50" maxaura="1.000000" regaura="1.000000" weight="20000" capacity="5000" speed="1.000000" hp="600" ac="3" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" scarepeasants="yes" swim="yes" teach="no" getitem="yes" resistbash="yes" unarmedguard="yes">
     <ai splitsize="6" killpeasants="yes" moverandom="yes" learn="yes" moveattack="yes"/>
     <skill name="tactics" modifier="4"/>
     <attack type="4" damage="1d30"/>
@@ -1202,7 +1202,7 @@
     <familiar race="wolf"/>
     <familiar race="demon"/>
   </race>
-  <race name="shadowdragon" magres="95" maxaura="1.000000" regaura="3.000000" weight="100" capacity="100000" speed="1.000000" hp="2700" ac="10" damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="12" scarepeasants="yes" fly="yes" walk="yes" canteach="no" getitem="yes" resistbash="yes">
+  <race name="shadowdragon" magres="95" maxaura="1.000000" regaura="3.000000" weight="100" capacity="100000" speed="1.000000" hp="2700" ac="10" damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="12" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes">
     <ai splitsize="1" killpeasants="yes" learn="yes"/>
     <skill name="tactics" modifier="20"/>
     <skill name="perception" modifier="20"/>
diff --git a/res/races/dragon.xml b/res/races/dragon.xml
index c9692cd9b..7625b914f 100644
--- a/res/races/dragon.xml
+++ b/res/races/dragon.xml
@@ -3,10 +3,9 @@
 <race name="dragon" magres="70" maxaura="1.0" regaura="2.000000" weight="10000" capacity="1000000" speed="1.500000" hp="900" ac=
 "6" damage="2d30" unarmedattack="0" unarmeddefense="0"
 attackmodifier="7" defensemodifier="7" scarepeasants="yes" fly="yes"
-income="1000" walk="yes" canteach="no" getitem="yes" resistbash="yes"
+income="1000" walk="yes" teach="no" getitem="yes" resistbash="yes"
 dragon="yes">
   <ai splitsize="2" killpeasants="yes" learn="yes" scare="400"/>
-  <function name="name" value="namedragon"/>
   <skill name="magic" modifier="8"/>
   <skill name="tactics" modifier="8"/>
   <attack type="4" damage="2d20"/>
diff --git a/res/races/wyrm.xml b/res/races/wyrm.xml
index df2008a80..c69ca2953 100644
--- a/res/races/wyrm.xml
+++ b/res/races/wyrm.xml
@@ -7,7 +7,6 @@ damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10"
 defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes"
 teach="no" getitem="yes" resistbash="yes" dragon="yes" income="5000">
   <ai splitsize="1" killpeasants="yes" learn="yes" scare="1000"/>
-  <function name="name" value="namedragon"/>
   <skill name="magic" modifier="12"/>
   <skill name="tactics" modifier="12"/>
   <attack type="4" damage="3d20"/>
diff --git a/res/races/youngdragon.xml b/res/races/youngdragon.xml
index d8b3d366f..bbfdb5a9f 100644
--- a/res/races/youngdragon.xml
+++ b/res/races/youngdragon.xml
@@ -6,7 +6,6 @@ damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4"
 defensemodifier="4" scarepeasants="yes" fly="yes" walk="yes"
 teach="no" getitem="yes" resistbash="yes" dragon="yes" income="150">
   <ai splitsize="6" killpeasants="yes" learn="yes" scare="160"/>
-  <function name="name" value="namedragon"/>
   <skill name="magic" modifier="4"/>
   <skill name="tactics" modifier="4"/>
   <attack type="4" damage="1d30"/>
diff --git a/src/exparse.c b/src/exparse.c
index e266d55ce..943b80741 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -878,13 +878,14 @@ static void XMLCALL start_ships(parseinfo *pi, const XML_Char *el, const XML_Cha
 }
 
 static int nattacks;
+static int nfamiliars;
 
 static void XMLCALL start_races(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     race *rc = (race *)pi->object;
     const char *flag_names[] = {
         "!playerrace", "killpeasants", "scarepeasants", "!cansteal",
         "moverandom", "cannotmove", "learn", "fly", "swim", "walk",
-        "!canlearn", "!canteach", "horse", "desert", "illusionary",
+        "!learn", "!teach", "horse", "desert", "illusionary",
         "absorbpeasants", "noheal", "noweapons", "shapeshift",
         "shapeshiftany", "undead", "dragon", "coastal", "unarmedguard",
         "cansail", "invisible", "shipspeed", "moveattack", "migrants", NULL };
@@ -922,10 +923,31 @@ static void XMLCALL start_races(parseinfo *pi, const XML_Char *el, const XML_Cha
             else if (xml_strcmp(key, "spell") == 0) {
                 at->data.sp = spellref_create(NULL, val);
             }
+            else {
+                handle_bad_input(pi, el, key);
+            }
         }
     }
     else if (xml_strcmp(el, "familiar") == 0) {
+        race *frc = NULL;
+        int i;
+
         assert(rc);
+        for (i = 0; attr[i]; i += 2) {
+            const XML_Char *key = attr[i], *val = attr[i + 1];
+            if (xml_strcmp(key, "race") == 0) {
+                frc = rc_get_or_create(val);
+                frc->flags |= RCF_FAMILIAR;
+            }
+            else {
+                handle_bad_input(pi, el, key);
+            }
+        }
+        if (frc) {
+            if (nfamiliars < MAXMAGIETYP) {
+                rc->familiars[nfamiliars++] = frc;
+            }
+        }
     }
     else if (xml_strcmp(el, "skill") == 0) {
         const XML_Char *name = NULL;
@@ -983,6 +1005,9 @@ static void XMLCALL start_races(parseinfo *pi, const XML_Char *el, const XML_Cha
     else if (xml_strcmp(el, "race") == 0) {
         const XML_Char *name;
 
+        nfamiliars = 0;
+        nattacks = 0;
+
         name = attr_get(attr, "name");
         if (name) {
             assert(!rc);
@@ -1279,6 +1304,13 @@ static void end_races(parseinfo *pi, const XML_Char *el) {
         assert(rc);
         rc->attack[nattacks].type = AT_NONE;
         nattacks = 0;
+        if (nfamiliars > 0 && nfamiliars < MAXMAGIETYP) {
+            int i;
+            for (i = nfamiliars - 1; i != MAXMAGIETYP; ++i) {
+                rc->familiars[i] = rc->familiars[nfamiliars - 1];
+            }
+        }
+        nfamiliars = 0;
         pi->object = NULL;
     }
     else if (xml_strcmp(el, "races") == 0) {
diff --git a/src/xmlreader.c b/src/xmlreader.c
index 53a8c1365..cf63a3ccb 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -1326,11 +1326,11 @@ static int parse_races(xmlDocPtr doc)
             rc->at_bonus = (char)xml_ivalue(node, "attackmodifier", rc->at_bonus);
             rc->df_bonus = (char)xml_ivalue(node, "defensemodifier", rc->df_bonus);
 
-            if (!xml_bvalue(node, "canteach", true))
+            if (!xml_bvalue(node, "teach", true))
                 rc->flags |= RCF_NOTEACH;
             if (!xml_bvalue(node, "cansteal", true))
                 rc->flags |= RCF_NOSTEAL;
-            if (!xml_bvalue(node, "canlearn", true))
+            if (!xml_bvalue(node, "learn", true))
                 rc->flags |= RCF_NOLEARN;
             if (!xml_bvalue(node, "playerrace", false)) {
                 assert(rc->recruitcost == 0);
@@ -1695,8 +1695,8 @@ void register_xmlreader(void)
     xml_register_callback(parse_ships);
     xml_register_callback(parse_spellbooks);
     xml_register_callback(parse_spells);
-#endif
     xml_register_callback(parse_races);
+#endif
     xml_register_callback(parse_equipment);
 
 

From 5de2a9e2aef1f5c72dd5ac8ca0f4951ef9ff3769 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Thu, 10 May 2018 21:05:51 +0200
Subject: [PATCH 45/59] fix ec_flags parsing (irongolem, etc)

---
 src/kernel/race.c |  2 +-
 src/kernel/race.h | 14 +++++++-------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/kernel/race.c b/src/kernel/race.c
index fa872778c..e77929fbf 100644
--- a/src/kernel/race.c
+++ b/src/kernel/race.c
@@ -310,7 +310,7 @@ static race *rc_find_i(const char *name)
         for (i = 0; rc_depr[i]; i += 2) {
             if (strcmp(name, rc_depr[i]) == 0) {
                 rc = rc_find_i(rc_depr[i + 1]);
-                log_warning("a reference was made to the retired race '%s', returning '%s'.", name, rc->_name);
+                log_info("a reference was made to the retired race '%s', returning '%s'.", name, rc->_name);
                 break;
             }
         }
diff --git a/src/kernel/race.h b/src/kernel/race.h
index 51c99e0f0..202b84d4b 100644
--- a/src/kernel/race.h
+++ b/src/kernel/race.h
@@ -236,13 +236,13 @@ extern "C" {
 #define RCF_DEFAULT (RCF_NOSTEAL|RCF_CANSAIL|RCF_NOLEARN)
 
     /* Economic flags */
-#define ECF_GIVEPERSON     (1<<2)   /* �bergibt Personen */
-#define ECF_GIVEUNIT       (1<<3)   /* Einheiten an andere Partei �bergeben */
-#define ECF_GETITEM        (1<<4)   /* nimmt Gegenst�nde an */
-#define ECF_REC_ETHEREAL   (1<<7)       /* Rekrutiert aus dem Nichts */
-#define ECF_REC_UNLIMITED  (1<<8)       /* Rekrutiert ohne Limit */
-#define ECF_STONEGOLEM     (1<<9)      /* race gets stonegolem properties */
-#define ECF_IRONGOLEM      (1<<10)      /* race gets irongolem properties */
+#define ECF_GIVEPERSON     (1<<0)   /* �bergibt Personen */
+#define ECF_GIVEUNIT       (1<<1)   /* Einheiten an andere Partei �bergeben */
+#define ECF_GETITEM        (1<<2)   /* nimmt Gegenst�nde an */
+#define ECF_REC_ETHEREAL   (1<<3)       /* Rekrutiert aus dem Nichts */
+#define ECF_REC_UNLIMITED  (1<<4)       /* Rekrutiert ohne Limit */
+#define ECF_STONEGOLEM     (1<<5)      /* race gets stonegolem properties */
+#define ECF_IRONGOLEM      (1<<6)      /* race gets irongolem properties */
 
     /* Battle-Flags */
 #define BF_EQUIPMENT    (1<<0)  /* Kann Ausr�stung benutzen */

From 9e16ebc01ad199165eeec4a633ae3e69351601c1 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Thu, 10 May 2018 22:00:23 +0200
Subject: [PATCH 46/59] all kinds of race flag breakage repaired. but now,
 humans suddenly can't build a ship in E2?

---
 src/exparse.c       |  2 +-
 src/jsonconf.c      |  7 +++----
 src/jsonconf.test.c |  6 +++---
 src/kernel/race.c   |  1 +
 src/kernel/race.h   |  6 +++---
 src/monsters.test.c | 14 +++++++++-----
 src/spy.test.c      |  3 +++
 src/tests.c         |  2 +-
 src/xmlreader.c     |  4 ++--
 9 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index 943b80741..b016c89df 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -883,7 +883,7 @@ static int nfamiliars;
 static void XMLCALL start_races(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     race *rc = (race *)pi->object;
     const char *flag_names[] = {
-        "!playerrace", "killpeasants", "scarepeasants", "!cansteal",
+        "playerrace", "killpeasants", "scarepeasants", "!cansteal",
         "moverandom", "cannotmove", "learn", "fly", "swim", "walk",
         "!learn", "!teach", "horse", "desert", "illusionary",
         "absorbpeasants", "noheal", "noweapons", "shapeshift",
diff --git a/src/jsonconf.c b/src/jsonconf.c
index 51727fe52..29881d6cf 100644
--- a/src/jsonconf.c
+++ b/src/jsonconf.c
@@ -480,17 +480,16 @@ static void json_ship(cJSON *json, ship_type *st) {
 static void json_race(cJSON *json, race *rc) {
     cJSON *child;
     const char *flags[] = {
-        "npc", "killpeasants", "scarepeasants",
+        "player", "killpeasants", "scarepeasants",
         "nosteal", "moverandom", "cannotmove",
         "learn", "fly", "swim", "walk", "nolearn",
         "noteach", "horse", "desert",
         "illusionary", "absorbpeasants", "noheal",
         "noweapons", "shapeshift", "", "undead", "dragon",
-        "coastal", "", "cansail", 0
+        "coastal", "", "cansail", NULL
     };
     const char *ecflags[] = {
-        "", "keepitem", "giveperson",
-        "giveunit", "getitem", 0
+        "giveperson", "giveunit", "getitem", NULL
     };
     if (json->type != cJSON_Object) {
         log_error("race %s is not a json object: %d", json->string, json->type);
diff --git a/src/jsonconf.test.c b/src/jsonconf.test.c
index 482337e40..7c15b63f1 100644
--- a/src/jsonconf.test.c
+++ b/src/jsonconf.test.c
@@ -56,7 +56,7 @@ static void check_flag(CuTest *tc, const char *name, int flag) {
 
 static void test_flags(CuTest *tc) {
     test_setup();
-    check_flag(tc, "npc", RCF_NPC);
+    check_flag(tc, "player", RCF_PLAYABLE);
     check_flag(tc, "scarepeasants", RCF_SCAREPEASANTS);
     check_flag(tc, "nosteal", RCF_NOSTEAL);
     check_flag(tc, "noheal", RCF_NOHEAL);
@@ -181,7 +181,7 @@ static void test_races(CuTest * tc)
         "\"income\" : 30,"
         "\"hp\" : 5,"
         "\"ac\" : 6,"
-        "\"flags\" : [ \"npc\", \"walk\", \"undead\" ]"
+        "\"flags\" : [ \"player\", \"walk\", \"undead\" ]"
         "}}}";
     cJSON *json = cJSON_Parse(data);
     const struct race *rc;
@@ -195,7 +195,7 @@ static void test_races(CuTest * tc)
     CuAssertPtrNotNull(tc, races);
     rc = rc_find("orc");
     CuAssertPtrNotNull(tc, rc);
-    CuAssertIntEquals(tc, RCF_NPC | RCF_WALK | RCF_UNDEAD, rc->flags);
+    CuAssertIntEquals(tc, RCF_PLAYABLE | RCF_WALK | RCF_UNDEAD, rc->flags);
     CuAssertStrEquals(tc, "1d4", rc->def_damage);
     CuAssertTrue(tc, frac_equal(frac_one, rc->magres));
     CuAssertIntEquals(tc, 200, rc->maxaura);
diff --git a/src/kernel/race.c b/src/kernel/race.c
index e77929fbf..ecdb7ae3d 100644
--- a/src/kernel/race.c
+++ b/src/kernel/race.c
@@ -356,6 +356,7 @@ race *rc_create(const char *zName)
 
     rc->magres.sa[1] = 1;
     rc->hitpoints = 1;
+    rc->flags = RCF_DEFAULT;
     rc->weight = PERSON_WEIGHT;
     rc->capacity = 540;
     rc->income = 20;
diff --git a/src/kernel/race.h b/src/kernel/race.h
index 202b84d4b..de0fd92e0 100644
--- a/src/kernel/race.h
+++ b/src/kernel/race.h
@@ -202,7 +202,7 @@ extern "C" {
     int rc_get_mask(char *list);
 
     /* Flags. Do not reorder these without changing json_race() in jsonconf.c */
-#define RCF_NPC            (1<<0)   /* cannot be the race for a player faction (and other limits?) */
+#define RCF_PLAYABLE       (1<<0)   /* cannot be the race for a player faction (and other limits?) */
 #define RCF_KILLPEASANTS   (1<<1)   /* a monster that eats peasants */
 #define RCF_SCAREPEASANTS  (1<<2)   /* a monster that scares peasants out of the hex */
 #define RCF_NOSTEAL        (1<<3)   /* this race has high stealth, but is not allowed to steal */
@@ -233,7 +233,7 @@ extern "C" {
 #define RCF_MIGRANTS       (1<<28)      /* may have migrant units (human bonus) */
 #define RCF_FAMILIAR       (1<<29)      /* may be a familiar */
 
-#define RCF_DEFAULT (RCF_NOSTEAL|RCF_CANSAIL|RCF_NOLEARN)
+#define RCF_DEFAULT 0
 
     /* Economic flags */
 #define ECF_GIVEPERSON     (1<<0)   /* �bergibt Personen */
@@ -256,7 +256,7 @@ extern "C" {
     const char *racename(const struct locale *lang, const struct unit *u,
         const race * rc);
 
-#define playerrace(rc) (!((rc)->flags & RCF_NPC))
+#define playerrace(rc) ((rc)->flags & RCF_PLAYABLE)
 #define dragonrace(rc) ((rc)->flags & RCF_DRAGON)
 #define humanoidrace(rc) (((rc)->flags & RCF_UNDEAD) || (rc)==get_race(RC_DRACOID) || playerrace(rc))
 #define illusionaryrace(rc) ((rc)->flags & RCF_ILLUSIONARY)
diff --git a/src/monsters.test.c b/src/monsters.test.c
index 409b86dfe..8fe9a6b7f 100644
--- a/src/monsters.test.c
+++ b/src/monsters.test.c
@@ -55,12 +55,16 @@ static void create_monsters(unit **up, unit **um) {
     test_create_horse();
     default_locale = test_create_locale();
     fp = test_create_faction(NULL);
+
     fm = get_or_create_monsters();
+    fset(fm, FFL_NOIDLEOUT);
+    assert(fval(fm, FFL_NPC));
+    assert(fval(fm, FFL_NOIDLEOUT));
+
     assert(rc_find(fm->race->_name));
     rc = rc_get_or_create(fm->race->_name);
-    fset(rc, RCF_UNARMEDGUARD|RCF_NPC|RCF_DRAGON);
-    fset(fm, FFL_NOIDLEOUT);
-    assert(fval(fm, FFL_NPC) && fval(fm->race, RCF_UNARMEDGUARD) && fval(fm->race, RCF_NPC) && fval(fm, FFL_NOIDLEOUT));
+    fset(rc, RCF_UNARMEDGUARD|RCF_DRAGON);
+    assert(!fval(fm->race, RCF_PLAYABLE));
 
     test_create_region(-1, 0, test_create_terrain("ocean", SEA_REGION | SWIM_INTO | FLY_INTO));
     test_create_region(1, 0, 0);
@@ -261,12 +265,12 @@ static void test_spawn_seaserpent(CuTest *tc) {
     race *rc;
     test_setup();
     rc = test_create_race("seaserpent");
-    rc->flags |= RCF_NPC;
+    rc->flags &= ~RCF_PLAYABLE;
     r = test_create_region(0, 0, NULL);
     f = test_create_faction(NULL);
     u = spawn_seaserpent(r, f);
     CuAssertPtrNotNull(tc, u);
-    CuAssertPtrEquals(tc, 0, u->_name);
+    CuAssertPtrEquals(tc, NULL, u->_name);
     test_teardown();
 }
 
diff --git a/src/spy.test.c b/src/spy.test.c
index c6a74822c..3c4503c98 100644
--- a/src/spy.test.c
+++ b/src/spy.test.c
@@ -196,7 +196,10 @@ static void test_setstealth_demon_bad(CuTest *tc) {
     lang = test_create_locale();
     rc = test_create_race("demon");
     u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, NULL));
+
     rc = test_create_race("smurf");
+    rc->flags &= ~RCF_PLAYABLE;
+
     init_races(lang);
     u->thisorder = create_order(K_SETSTEALTH, lang, racename(lang, u, rc));
     setstealth_cmd(u, u->thisorder);
diff --git a/src/tests.c b/src/tests.c
index 696baf447..ad9f8eddf 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -43,7 +43,7 @@ struct race *test_create_race(const char *name)
     rc->maintenance = 10;
     rc->hitpoints = 20;
     rc->maxaura = 100;
-    rc->flags |= RCF_WALK;
+    rc->flags |= (RCF_WALK|RCF_PLAYABLE);
     rc->ec_flags |= ECF_GETITEM;
     rc->battle_flags = BF_EQUIPMENT;
     return rc;
diff --git a/src/xmlreader.c b/src/xmlreader.c
index cf63a3ccb..b0a0aafcc 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -1332,9 +1332,9 @@ static int parse_races(xmlDocPtr doc)
                 rc->flags |= RCF_NOSTEAL;
             if (!xml_bvalue(node, "learn", true))
                 rc->flags |= RCF_NOLEARN;
-            if (!xml_bvalue(node, "playerrace", false)) {
+            if (xml_bvalue(node, "playerrace", false)) {
                 assert(rc->recruitcost == 0);
-                rc->flags |= RCF_NPC;
+                rc->flags |= RCF_PLAYABLE;
             }
             if (xml_bvalue(node, "scarepeasants", false))
                 rc->flags |= RCF_SCAREPEASANTS;

From 84bc08a38116d650546fdd046948d4ed28773ad7 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Thu, 10 May 2018 22:10:26 +0200
Subject: [PATCH 47/59] all races can be on a boat by default. but now MAKETEMP
 is broken. prefer assert_(not_)nil over assert_(not_)equal

---
 scripts/tests/common.lua        | 32 ++++++++++++++++----------------
 scripts/tests/e2/production.lua |  4 ++--
 src/kernel/race.h               |  2 +-
 src/kernel/race.test.c          |  2 +-
 4 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/scripts/tests/common.lua b/scripts/tests/common.lua
index b77606266..511f275db 100644
--- a/scripts/tests/common.lua
+++ b/scripts/tests/common.lua
@@ -155,7 +155,7 @@ end
 
 function test_pure()
   local r = region.create(0, 0, "plain")
-  assert_not_equal(nil, r)
+  assert_not_nil(r)
   assert_equal(r, get_region(0, 0))
 end
 
@@ -170,21 +170,21 @@ function test_read_write()
   assert_equal(r.terrain, "plain")
   result = eressea.write_game("test.dat")
   assert_equal(result, 0)
-  assert_not_equal(get_region(0, 0), nil)
-  assert_not_equal(get_faction(fno), nil)
-  assert_not_equal(get_unit(uno), nil)
+  assert_not_nil(get_region(0, 0))
+  assert_not_nil(get_faction(fno))
+  assert_not_nil(get_unit(uno))
   r = nil
   f = nil
   u = nil
   eressea.free_game()
-  assert_equal(get_region(0, 0), nil)
-  assert_equal(nil, get_faction(fno))
-  assert_equal(nil, get_unit(uno))
+  assert_nil(get_region(0, 0))
+  assert_nil(get_faction(fno))
+  assert_nil(get_unit(uno))
   result = eressea.read_game("test.dat")
   assert_equal(0, result)
-  assert_not_equal(nil, get_region(0, 0))
-  assert_not_equal(nil, get_faction(fno))
-  assert_not_equal(nil, get_unit(uno))
+  assert_not_nil(get_region(0, 0))
+  assert_not_nil(get_faction(fno))
+  assert_not_nil(get_unit(uno))
 end
 
 function test_descriptions()
@@ -238,7 +238,7 @@ function test_gmtool()
         selections=selections+1
     end
     assert_equal(2, selections)
-    assert_equal(nil, gmtool.get_cursor())
+    assert_nil(gmtool.get_cursor())
 
     gmtool.close()
 end
@@ -568,7 +568,7 @@ function test_coordinate_translation()
     local pe = plane.create(1, -8761, 3620, 23, 23) -- eternath
     local r = region.create(1000, 1000, "plain")
     local f = create_faction('human')
-    assert_not_equal(nil, r)
+    assert_not_nil(r)
     assert_equal(r.x, 1000)
     assert_equal(r.y, 1000)
     local nx, ny = plane.normalize(pl, r.x, r.y)
@@ -634,8 +634,8 @@ end
 -- segfault above
 
 function test_config()
-  assert_not_equal(nil, config.basepath)
-  assert_not_equal(nil, config.locales)
+  assert_not_nil(config.basepath)
+  assert_not_nil(config.locales)
 end
 
 local function _test_create_laen()
@@ -827,9 +827,9 @@ function test_swim_and_die()
     process_orders()
     r.terrain = "ocean"
     u = get_unit(uid)
-    assert_not_equal(get_unit(uid), nil)
+    assert_not_nil(get_unit(uid))
     process_orders()
-    assert_equal(get_unit(uid), nil)
+    assert_nil(get_unit(uid))
 end
 
 function test_ride_with_horse()
diff --git a/scripts/tests/e2/production.lua b/scripts/tests/e2/production.lua
index 5070d02f6..852d8f629 100644
--- a/scripts/tests/e2/production.lua
+++ b/scripts/tests/e2/production.lua
@@ -101,14 +101,14 @@ function test_build_boat_low_skill()
     u:add_item("log", 10)
     u:add_order("MACHE BOOT")
     process_orders()
-    assert_not_equal(nil, u.ship)
+    assert_not_nil(u.ship)
     assert_equal(4, u.ship.size)
     assert_equal(6, u:get_item('log'))
 end
 
 function test_build_boat_high_skill()
     local r = region.create(0, 0, "plain")
-    local f = faction.create("human", "build@example.com")
+    local f = faction.create("human", "skillz@example.com")
     local u = unit.create(f, r, 1)
     u:set_skill("shipcraft", 5) -- humans get +1
     u:add_item("log", 10)
diff --git a/src/kernel/race.h b/src/kernel/race.h
index de0fd92e0..65cb0cf73 100644
--- a/src/kernel/race.h
+++ b/src/kernel/race.h
@@ -233,7 +233,7 @@ extern "C" {
 #define RCF_MIGRANTS       (1<<28)      /* may have migrant units (human bonus) */
 #define RCF_FAMILIAR       (1<<29)      /* may be a familiar */
 
-#define RCF_DEFAULT 0
+#define RCF_DEFAULT RCF_CANSAIL
 
     /* Economic flags */
 #define ECF_GIVEPERSON     (1<<0)   /* �bergibt Personen */
diff --git a/src/kernel/race.test.c b/src/kernel/race.test.c
index e1c255ef2..ac0609a69 100644
--- a/src/kernel/race.test.c
+++ b/src/kernel/race.test.c
@@ -50,7 +50,7 @@ static void test_rc_defaults(CuTest *tc) {
     CuAssertDblEquals(tc, 1.0, rc->recruit_multi, 0.0);
     CuAssertDblEquals(tc, 1.0, rc->regaura, 0.0);
     CuAssertDblEquals(tc, 1.0, rc->speed, 0.0);
-    CuAssertIntEquals(tc, 0, rc->flags);
+    CuAssertIntEquals(tc, RCF_DEFAULT, rc->flags);
     CuAssertIntEquals(tc, 0, rc->recruitcost);
     CuAssertIntEquals(tc, 0, rc->maintenance);
     CuAssertIntEquals(tc, 540, rc->capacity);

From 89ecc54bdd809604d3fe98eace262f9daa250460 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Thu, 10 May 2018 22:20:28 +0200
Subject: [PATCH 48/59] deal with jsonconf defaults.

---
 scripts/tests/laws.lua | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/scripts/tests/laws.lua b/scripts/tests/laws.lua
index 3a724a440..6dc37daf7 100644
--- a/scripts/tests/laws.lua
+++ b/scripts/tests/laws.lua
@@ -6,7 +6,7 @@ function setup()
     eressea.free_game()
     conf = [[{
         "races": {
-            "human" : {}
+            "human" : { "flags" : [ "player" ] }
         },
         "terrains" : {
             "plain": { "flags" : [ "land", "walk", "sail" ] }
@@ -61,7 +61,7 @@ end
 
 function test_make_temp()
     local r = region.create(0, 0, "plain")
-    local f1 = faction.create("human", "owner@eressea.de", "de")
+    local f1 = faction.create("human", "temp@eressea.de", "de")
     local u1 = unit.create(f1, r, 10)
     local u, u2
 

From f8b8a5284c0ccdad4d6ded0f58b599c9702ad3a8 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 18 May 2018 18:50:13 +0200
Subject: [PATCH 49/59] begin expat message parsing

---
 src/exparse.c        | 27 +++++++++++++++++++++++----
 src/util/message.c   | 13 +++++--------
 src/util/nrmessage.c |  8 ++++----
 3 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index b016c89df..e323bb74c 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -16,6 +16,7 @@
 
 #include "util/functions.h"
 #include "util/log.h"
+#include "util/message.h"
 #include "util/strings.h"
 
 #include <expat.h>
@@ -47,7 +48,6 @@ enum {
     EXP_SHIPS,
     EXP_RACES,
     EXP_MESSAGES,
-    EXP_STRINGS,
     EXP_SPELLS,
     EXP_SPELLBOOKS,
 };
@@ -285,6 +285,25 @@ static void handle_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **at
     wtype->flags = flags;
 }
 
+static void XMLCALL start_messages(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    if (xml_strcmp(el, "message") == 0) {
+        const XML_Char *name = NULL, *section = NULL;
+        int i;
+        for (i = 0; attr[i]; i += 2) {
+            const XML_Char *key = attr[i], *val = attr[i + 1];
+            if (xml_strcmp(key, "name") == 0) {
+                name = val;
+            }
+            else if (xml_strcmp(key, "section") == 0) {
+                section = val;
+            }
+        }
+        if (name) {
+            pi->object = mt_new(name, NULL);
+        }
+    }
+}
+
 #define MAX_COMPONENTS 8
 static spell_component components[MAX_COMPONENTS];
 static int ncomponents;
@@ -1192,9 +1211,6 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
         else if (xml_strcmp(el, "messages") == 0) {
             pi->type = EXP_MESSAGES;
         }
-        else if (xml_strcmp(el, "strings") == 0) {
-            pi->type = EXP_STRINGS;
-        }
         else if (xml_strcmp(el, "spells") == 0) {
             pi->type = EXP_SPELLS;
         }
@@ -1232,6 +1248,9 @@ static void XMLCALL handle_start(void *data, const XML_Char *el, const XML_Char
         case EXP_SPELLS:
             start_spells(pi, el, attr);
             break;
+        case EXP_MESSAGES:
+            start_messages(pi, el, attr);
+            break;
         case EXP_UNKNOWN:
             handle_bad_input(pi, el, NULL);
             break;
diff --git a/src/util/message.c b/src/util/message.c
index a919f5f7d..71795cfc7 100644
--- a/src/util/message.c
+++ b/src/util/message.c
@@ -79,16 +79,9 @@ message_type *mt_new(const char *name, const char *args[])
     mtype->name = str_strdup(name);
     mtype->nparameters = nparameters;
     if (nparameters > 0) {
+        int i;
         mtype->pnames = (char **)malloc(sizeof(char *) * nparameters);
         mtype->types = (arg_type **)malloc(sizeof(arg_type *) * nparameters);
-    }
-    else {
-        mtype->pnames = NULL;
-        mtype->types = NULL;
-    }
-    if (args != NULL) {
-        int i;
-
         for (i = 0; args[i]; ++i) {
             const char *x = args[i];
             const char *spos = strchr(x, ':');
@@ -110,6 +103,10 @@ message_type *mt_new(const char *name, const char *args[])
             }
         }
     }
+    else {
+        mtype->pnames = NULL;
+        mtype->types = NULL;
+    }
     return mtype;
 }
 
diff --git a/src/util/nrmessage.c b/src/util/nrmessage.c
index 2df1f4864..9461e11c5 100644
--- a/src/util/nrmessage.c
+++ b/src/util/nrmessage.c
@@ -27,10 +27,10 @@
 #include <stdlib.h>
 
 typedef struct nrmessage_type {
-  const struct message_type *mtype;
-  char *vars;
-  struct nrmessage_type *next;
-  const char *section;
+    const struct message_type *mtype;
+    char *vars;
+    struct nrmessage_type *next;
+    const char *section;
 } nrmessage_type;
 
 #define NRT_MAXHASH 1021

From 19b3b5b35a271610f142189cdc7247fc25d38774 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 18 May 2018 19:58:49 +0200
Subject: [PATCH 50/59] change how message types are created (more prep work
 for expat)

---
 src/creport.c                     |  2 +-
 src/donations.test.c              |  2 +-
 src/economy.test.c                | 18 +++----
 src/give.test.c                   | 34 ++++++------
 src/kernel/build.test.c           |  2 +-
 src/kernel/messages.c             |  6 +--
 src/kernel/messages.test.c        |  8 +--
 src/laws.test.c                   | 30 +++++------
 src/market.test.c                 |  2 +-
 src/monsters.test.c               |  5 +-
 src/move.test.c                   | 18 ++++---
 src/orderfile.test.c              |  2 +-
 src/piracy.test.c                 | 18 ++++---
 src/renumber.test.c               |  2 +-
 src/report.c                      | 15 +++---
 src/spells.test.c                 |  6 ++-
 src/spells/flyingship.test.c      |  3 +-
 src/spells/magicresistance.test.c |  6 ++-
 src/spy.test.c                    | 39 +++++++++-----
 src/study.test.c                  | 18 ++++---
 src/tests.c                       |  9 ++--
 src/triggers/shock.test.c         |  3 +-
 src/util/message.c                | 88 +++++++++++++++----------------
 src/util/message.h                |  7 +--
 src/util/message.test.c           |  3 +-
 src/util/nrmessage.c              | 65 +++++++++--------------
 src/util/nrmessage.h              | 11 ++--
 src/volcano.test.c                | 12 +++--
 src/wormhole.test.c               | 12 +++--
 src/xmlreader.c                   | 24 ++++-----
 30 files changed, 250 insertions(+), 220 deletions(-)

diff --git a/src/creport.c b/src/creport.c
index 325d0dec0..17cf60fdb 100644
--- a/src/creport.c
+++ b/src/creport.c
@@ -519,7 +519,7 @@ static void report_crtypes(FILE * F, const struct locale *lang)
             fputc('\"', F);
             fputs(str_escape(nrt_string(kmt->mtype, lang), buffer, sizeof(buffer)), F);
             fputs("\";text\n", F);
-            fprintf(F, "\"%s\";section\n", nrt_section(kmt->mtype));
+            fprintf(F, "\"%s\";section\n", kmt->mtype->section);
         }
         while (mtypehash[i]) {
             kmt = mtypehash[i];
diff --git a/src/donations.test.c b/src/donations.test.c
index a3a428a73..2cdc8f174 100644
--- a/src/donations.test.c
+++ b/src/donations.test.c
@@ -13,7 +13,7 @@ static void test_add_donation(CuTest *tc) {
     region *r;
 
     test_setup();
-    mt_register(mt_new_va("donation", "from:faction", "to:faction", "amount:int", MT_NEW_END));
+    mt_create_va(mt_new("donation", NULL), "from:faction", "to:faction", "amount:int", MT_NEW_END);
     r = test_create_region(0, 0, NULL);
     f1 = test_create_faction(NULL);
     f2 = test_create_faction(NULL);
diff --git a/src/economy.test.c b/src/economy.test.c
index 0ed869ef0..3b5745be4 100644
--- a/src/economy.test.c
+++ b/src/economy.test.c
@@ -143,10 +143,10 @@ static struct unit *create_recruiter(void) {
 
 static void setup_production(void) {
     init_resources();
-    mt_register(mt_new_va("produce", "unit:unit", "region:region", "amount:int", "wanted:int", "resource:resource", MT_NEW_END));
-    mt_register(mt_new_va("income", "unit:unit", "region:region", "amount:int", "wanted:int", "mode:int", MT_NEW_END));
-    mt_register(mt_new_va("buy", "unit:unit", "money:int", MT_NEW_END));
-    mt_register(mt_new_va("buyamount", "unit:unit", "amount:int", "resource:resource", MT_NEW_END));
+    mt_create_va(mt_new("produce", NULL), "unit:unit", "region:region", "amount:int", "wanted:int", "resource:resource", MT_NEW_END);
+    mt_create_va(mt_new("income", NULL), "unit:unit", "region:region", "amount:int", "wanted:int", "mode:int", MT_NEW_END);
+    mt_create_va(mt_new("buy", NULL), "unit:unit", "money:int", MT_NEW_END);
+    mt_create_va(mt_new("buyamount", NULL), "unit:unit", "amount:int", "resource:resource", MT_NEW_END);
 }
 
 static void test_heroes_dont_recruit(CuTest * tc) {
@@ -378,11 +378,11 @@ static void test_tax_cmd(CuTest *tc) {
 }
 
 static void setup_economy(void) {
-    mt_register(mt_new_va("recruit", "unit:unit", "region:region", "amount:int", "want:int", MT_NEW_END));
-    mt_register(mt_new_va("maintenance", "unit:unit", "building:building", MT_NEW_END));
-    mt_register(mt_new_va("maintenancefail", "unit:unit", "building:building", MT_NEW_END));
-    mt_register(mt_new_va("maintenance_nowork", "building:building", MT_NEW_END));
-    mt_register(mt_new_va("maintenance_noowner", "building:building", MT_NEW_END));
+    mt_create_va(mt_new("recruit", NULL), "unit:unit", "region:region", "amount:int", "want:int", MT_NEW_END);
+    mt_create_va(mt_new("maintenance", NULL), "unit:unit", "building:building", MT_NEW_END);
+    mt_create_va(mt_new("maintenancefail", NULL), "unit:unit", "building:building", MT_NEW_END);
+    mt_create_va(mt_new("maintenance_nowork", NULL), "building:building", MT_NEW_END);
+    mt_create_va(mt_new("maintenance_noowner", NULL), "building:building", MT_NEW_END);
 }
 
 /** 
diff --git a/src/give.test.c b/src/give.test.c
index 3e58216c9..d02c27e6f 100644
--- a/src/give.test.c
+++ b/src/give.test.c
@@ -54,24 +54,24 @@ static void setup_give(struct give *env) {
     }
 
     /* success messages: */
-    mt_register(mt_new_va("receive_person", "unit:unit", "target:unit", "amount:int", MT_NEW_END));
-    mt_register(mt_new_va("give_person", "unit:unit", "target:unit", "amount:int", MT_NEW_END));
-    mt_register(mt_new_va("give_person_peasants", "unit:unit", "amount:int", MT_NEW_END));
-    mt_register(mt_new_va("give_person_ocean", "unit:unit", "amount:int", MT_NEW_END));
-    mt_register(mt_new_va("receive", "unit:unit", "target:unit", "resource:resource", "amount:int", MT_NEW_END));
-    mt_register(mt_new_va("give", "unit:unit", "target:unit", "resource:resource", "amount:int", MT_NEW_END));
-    mt_register(mt_new_va("give_peasants", "unit:unit", "resource:resource", "amount:int", MT_NEW_END));
+    mt_create_va(mt_new("receive_person", NULL), "unit:unit", "target:unit", "amount:int", MT_NEW_END);
+    mt_create_va(mt_new("give_person", NULL), "unit:unit", "target:unit", "amount:int", MT_NEW_END);
+    mt_create_va(mt_new("give_person_peasants", NULL), "unit:unit", "amount:int", MT_NEW_END);
+    mt_create_va(mt_new("give_person_ocean", NULL), "unit:unit", "amount:int", MT_NEW_END);
+    mt_create_va(mt_new("receive", NULL), "unit:unit", "target:unit", "resource:resource", "amount:int", MT_NEW_END);
+    mt_create_va(mt_new("give", NULL), "unit:unit", "target:unit", "resource:resource", "amount:int", MT_NEW_END);
+    mt_create_va(mt_new("give_peasants", NULL), "unit:unit", "resource:resource", "amount:int", MT_NEW_END);
     /* error messages: */
-    mt_register(mt_new_va("too_many_units_in_faction", "unit:unit", "region:region", "command:order", "allowed:int", MT_NEW_END));
-    mt_register(mt_new_va("too_many_units_in_alliance", "unit:unit", "region:region", "command:order", "allowed:int", MT_NEW_END));
-    mt_register(mt_new_va("feedback_no_contact", "unit:unit", "region:region", "command:order", "target:unit", MT_NEW_END));
-    mt_register(mt_new_va("feedback_give_forbidden", "unit:unit", "region:region", "command:order", MT_NEW_END));
-    mt_register(mt_new_va("peasants_give_invalid", "unit:unit", "region:region", "command:order", MT_NEW_END));
-    mt_register(mt_new_va("giverestriction", "unit:unit", "region:region", "command:order", "turns:int", MT_NEW_END));
-    mt_register(mt_new_va("error_unit_size", "unit:unit", "region:region", "command:order", "maxsize:int", MT_NEW_END));
-    mt_register(mt_new_va("nogive_reserved", "unit:unit", "region:region", "command:order", "resource:resource", "reservation:int", MT_NEW_END));
-    mt_register(mt_new_va("race_notake", "unit:unit", "region:region", "command:order", "race:race", MT_NEW_END));
-    mt_register(mt_new_va("race_noregroup", "unit:unit", "region:region", "command:order", "race:race", MT_NEW_END));
+    mt_create_va(mt_new("too_many_units_in_faction", NULL), "unit:unit", "region:region", "command:order", "allowed:int", MT_NEW_END);
+    mt_create_va(mt_new("too_many_units_in_alliance", NULL), "unit:unit", "region:region", "command:order", "allowed:int", MT_NEW_END);
+    mt_create_va(mt_new("feedback_no_contact", NULL), "unit:unit", "region:region", "command:order", "target:unit", MT_NEW_END);
+    mt_create_va(mt_new("feedback_give_forbidden", NULL), "unit:unit", "region:region", "command:order", MT_NEW_END);
+    mt_create_va(mt_new("peasants_give_invalid", NULL), "unit:unit", "region:region", "command:order", MT_NEW_END);
+    mt_create_va(mt_new("giverestriction", NULL), "unit:unit", "region:region", "command:order", "turns:int", MT_NEW_END);
+    mt_create_va(mt_new("error_unit_size", NULL), "unit:unit", "region:region", "command:order", "maxsize:int", MT_NEW_END);
+    mt_create_va(mt_new("nogive_reserved", NULL), "unit:unit", "region:region", "command:order", "resource:resource", "reservation:int", MT_NEW_END);
+    mt_create_va(mt_new("race_notake", NULL), "unit:unit", "region:region", "command:order", "race:race", MT_NEW_END);
+    mt_create_va(mt_new("race_noregroup", NULL), "unit:unit", "region:region", "command:order", "race:race", MT_NEW_END);
 }
 
 static void test_give_unit(CuTest * tc) {
diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c
index 1261e5496..9bae742c2 100644
--- a/src/kernel/build.test.c
+++ b/src/kernel/build.test.c
@@ -253,7 +253,7 @@ static void test_build_destroy_road(CuTest *tc)
     message *m;
 
     test_setup();
-    mt_register(mt_new_va("destroy_road", "unit:unit", "from:region", "to:region", MT_NEW_END));
+    mt_create_va(mt_new("destroy_road", NULL), "unit:unit", "from:region", "to:region", MT_NEW_END);
     r2 = test_create_region(1, 0, 0);
     r = test_create_region(0, 0, NULL);
     rsetroad(r, D_EAST, 100);
diff --git a/src/kernel/messages.c b/src/kernel/messages.c
index 9875d303e..e0513b00d 100644
--- a/src/kernel/messages.c
+++ b/src/kernel/messages.c
@@ -82,8 +82,8 @@ struct message *msg_feedback(const struct unit *u, struct order *ord,
     if (!mtype) {
         log_warning("trying to create message of unknown type \"%s\"\n", name);
         if (!mt_find("missing_feedback")) {
-            mt_register(mt_new_va("missing_feedback", "unit:unit", 
-                "region:region", "command:order", "name:string", MT_NEW_END));
+            mt_create_va(mt_new("missing_feedback", NULL), "unit:unit", 
+                "region:region", "command:order", "name:string", MT_NEW_END);
         }
         return msg_message("missing_feedback", "name unit region command",
             name, u, u->region, ord);
@@ -153,7 +153,7 @@ static message *missing_message(const char *name) {
         log_warning("trying to create undefined message of type \"%s\"\n", name);
         if (strcmp(name, "missing_message") != 0) {
             if (!mt_find("missing_message")) {
-                mt_register(mt_new_va("missing_message", "name:string", MT_NEW_END));
+                mt_create_va(mt_new("missing_message", NULL), "name:string", MT_NEW_END);
             }
             return msg_message("missing_message", "name", name);
         }
diff --git a/src/kernel/messages.test.c b/src/kernel/messages.test.c
index ad6a08071..961d2e63a 100644
--- a/src/kernel/messages.test.c
+++ b/src/kernel/messages.test.c
@@ -22,10 +22,10 @@ void test_missing_message(CuTest *tc) {
 
 void test_message(CuTest *tc) {
     message *msg;
-    message_type *mtype = mt_new("custom", NULL);
+    message_type *mtype;
 
     test_setup();
-    mt_register(mtype);
+    mtype = mt_create(mt_new("custom", NULL), NULL);
     CuAssertPtrEquals(tc, mtype, (void *)mt_find("custom"));
     CuAssertIntEquals(tc, 0, mtype->nparameters);
     CuAssertPtrEquals(tc, NULL, (void *)mtype->pnames);
@@ -47,11 +47,11 @@ void test_message(CuTest *tc) {
 static void test_merge_split(CuTest *tc) {
     message_list *mlist = 0, *append = 0;
     struct mlist **split; /* TODO: why is this a double asterisk? */
-    message_type *mtype = mt_new("custom", NULL);
+    message_type *mtype;
     message *msg;
 
     test_setup();
-    mt_register(mtype);
+    mtype = mt_create(mt_new("custom", NULL), NULL);
     add_message(&mlist, msg = msg_message(mtype->name, ""));
     msg_release(msg);
     add_message(&append, msg = msg_message(mtype->name, ""));
diff --git a/src/laws.test.c b/src/laws.test.c
index f9b4cfcf3..8d13b7c81 100644
--- a/src/laws.test.c
+++ b/src/laws.test.c
@@ -258,7 +258,7 @@ static void test_force_leave_buildings(CuTest *tc) {
     building * b;
 
     test_setup();
-    mt_register(mt_new_va("force_leave_building", "unit:unit", "owner:unit", "building:building", MT_NEW_END));
+    mt_create_va(mt_new("force_leave_building", NULL), "unit:unit", "owner:unit", "building:building", MT_NEW_END);
     r = test_create_region(0, 0, test_create_terrain("plain", LAND_REGION));
     u1 = test_create_unit(test_create_faction(NULL), r);
     u2 = test_create_unit(u1->faction, r);
@@ -288,7 +288,7 @@ static void test_force_leave_ships(CuTest *tc) {
     ship *sh;
 
     test_setup();
-    mt_register(mt_new_va("force_leave_ship", "unit:unit", "owner:unit", "ship:ship", MT_NEW_END));
+    mt_create_va(mt_new("force_leave_ship", NULL), "unit:unit", "owner:unit", "ship:ship", MT_NEW_END);
     r = test_create_region(0, 0, test_create_terrain("plain", LAND_REGION));
     u1 = test_create_unit(test_create_faction(NULL), r);
     u2 = test_create_unit(test_create_faction(NULL), r);
@@ -876,7 +876,7 @@ static void test_luck_message(CuTest *tc) {
     attrib *a;
 
     test_setup();
-    mt_register(mt_new_va("peasantluck_success", "births:int", MT_NEW_END));
+    mt_create_va(mt_new("peasantluck_success", NULL), "births:int", MT_NEW_END);
     setup_terrains(tc);
     r = test_create_region(0, 0, NULL);
     rsetpeasants(r, 1);
@@ -901,8 +901,8 @@ static unit * setup_name_cmd(void) {
     faction *f;
 
     test_setup();
-    mt_register(mt_new_va("renamed_building_seen", "renamer:unit", "region:region", "building:building", MT_NEW_END));
-    mt_register(mt_new_va("renamed_building_notseen", "region:region", "building:building", MT_NEW_END));
+    mt_create_va(mt_new("renamed_building_seen", NULL), "renamer:unit", "region:region", "building:building", MT_NEW_END);
+    mt_create_va(mt_new("renamed_building_notseen", NULL), "region:region", "building:building", MT_NEW_END);
     f = test_create_faction(NULL);
     return test_create_unit(f, test_create_region(0, 0, NULL));
 }
@@ -1301,9 +1301,9 @@ static void test_ally_cmd(CuTest *tc) {
 static void test_nmr_warnings(CuTest *tc) {
     faction *f1, *f2;
     test_setup();
-    mt_register(mt_new_va("nmr_warning", MT_NEW_END));
-    mt_register(mt_new_va("nmr_warning_final", MT_NEW_END));
-    mt_register(mt_new_va("warn_dropout", "faction:faction", "turn:int", MT_NEW_END));
+    mt_create_va(mt_new("nmr_warning", NULL), MT_NEW_END);
+    mt_create_va(mt_new("nmr_warning_final", NULL), MT_NEW_END);
+    mt_create_va(mt_new("warn_dropout", NULL), "faction:faction", "turn:int", MT_NEW_END);
     config_set("nmr.timeout", "3");
     f1 = test_create_faction(NULL);
     f2 = test_create_faction(NULL);
@@ -1325,9 +1325,9 @@ static unit * setup_mail_cmd(void) {
     faction *f;
     
     test_setup();
-    mt_register(mt_new_va("regionmessage", "region:region", "sender:unit", "string:string", MT_NEW_END));
-    mt_register(mt_new_va("unitmessage", "region:region", "sender:unit", "string:string", "unit:unit", MT_NEW_END));
-    mt_register(mt_new_va("mail_result", "message:string", "unit:unit", MT_NEW_END));
+    mt_create_va(mt_new("regionmessage", NULL), "region:region", "sender:unit", "string:string", MT_NEW_END);
+    mt_create_va(mt_new("unitmessage", NULL), "region:region", "sender:unit", "string:string", "unit:unit", MT_NEW_END);
+    mt_create_va(mt_new("mail_result", NULL), "message:string", "unit:unit", MT_NEW_END);
     f = test_create_faction(NULL);
     return test_create_unit(f, test_create_region(0, 0, NULL));
 }
@@ -1444,7 +1444,7 @@ static void test_show_without_item(CuTest *tc)
     struct locale *loc;
 
     test_setup();
-    mt_register(mt_new_va("displayitem", "weight:int", "item:resource", "description:string", MT_NEW_END));
+    mt_create_va(mt_new("displayitem", NULL), "weight:int", "item:resource", "description:string", MT_NEW_END);
 
     loc = get_or_create_locale("de");
     locale_setstring(loc, parameters[P_ANY], "ALLE");
@@ -1489,7 +1489,7 @@ static void test_show_race(CuTest *tc) {
 
     test_setup();
 
-    mt_register(mt_new_va("msg_event", "string:string", MT_NEW_END));
+    mt_create_va(mt_new("msg_event", NULL), "string:string", MT_NEW_END);
     test_create_race("human");
     rc = test_create_race("elf");
 
@@ -1529,8 +1529,8 @@ static void test_show_both(CuTest *tc) {
     message * msg;
 
     test_setup();
-    mt_register(mt_new_va("msg_event", "string:string", MT_NEW_END));
-    mt_register(mt_new_va("displayitem", "weight:int", "item:resource", "description:string", MT_NEW_END));
+    mt_create_va(mt_new("msg_event", NULL), "string:string", MT_NEW_END);
+    mt_create_va(mt_new("displayitem", NULL), "weight:int", "item:resource", "description:string", MT_NEW_END);
     rc = test_create_race("elf");
     test_create_itemtype("elvenhorse");
 
diff --git a/src/market.test.c b/src/market.test.c
index 452f75091..4877dbf29 100644
--- a/src/market.test.c
+++ b/src/market.test.c
@@ -33,7 +33,7 @@ static void test_market_curse(CuTest * tc)
     building_type *btype;
 
     test_setup();
-    mt_register(mt_new_va("buyamount", "unit:unit", "amount:int", "resource:resource", MT_NEW_END));
+    mt_create_va(mt_new("buyamount", NULL), "unit:unit", "amount:int", "resource:resource", MT_NEW_END);
 
     htype = test_create_itemtype("herb");
     htype->flags |= ITF_HERB;
diff --git a/src/monsters.test.c b/src/monsters.test.c
index 8fe9a6b7f..54b3f7f87 100644
--- a/src/monsters.test.c
+++ b/src/monsters.test.c
@@ -51,7 +51,8 @@ static void create_monsters(unit **up, unit **um) {
     region *r;
     faction *fp, *fm;
 
-    mt_register(mt_new_va("dragon_growl", "dragon:unit", "number:int", "target:region", "growl:string", MT_NEW_END));
+    mt_create_va(mt_new("dragon_growl", NULL),
+        "dragon:unit", "number:int", "target:region", "growl:string", MT_NEW_END);
     test_create_horse();
     default_locale = test_create_locale();
     fp = test_create_faction(NULL);
@@ -223,8 +224,6 @@ static void test_dragon_moves(CuTest * tc)
     plan_monsters(m->faction);
     CuAssertPtrNotNull(tc, find_order("move east", m));
 
-    mt_register(mt_new_va("dragon_growl", "dragon:unit", "number:int", "target:region", "growl:string", MT_NEW_END));
-
     random_growl(m, findregion(1, 0), 3);
 
     msg = test_get_last_message(r->msgs);
diff --git a/src/move.test.c b/src/move.test.c
index 07fde591c..a2fa4e760 100644
--- a/src/move.test.c
+++ b/src/move.test.c
@@ -28,8 +28,10 @@
 #include <assert.h>
 
 static void setup_move(void) {
-    mt_register(mt_new_va("travel", "unit:unit", "start:region", "end:region", "mode:int", "regions:regions", MT_NEW_END));
-    mt_register(mt_new_va("moveblocked", "unit:unit", "direction:int", MT_NEW_END));
+    mt_create_va(mt_new("travel", NULL),
+        "unit:unit", "start:region", "end:region", "mode:int", "regions:regions", MT_NEW_END);
+    mt_create_va(mt_new("moveblocked", NULL),
+        "unit:unit", "direction:int", MT_NEW_END);
 }
 
 static void test_ship_not_allowed_in_coast(CuTest * tc)
@@ -285,9 +287,12 @@ void setup_drift (struct drift_fixture *fix) {
     u_set_ship(fix->u, fix->sh = test_create_ship(fix->u->region, fix->st_boat));
     assert(fix->sh);
 
-    mt_register(mt_new_va("ship_drift", "ship:ship", "dir:int", MT_NEW_END));
-    mt_register(mt_new_va("shipsink", "ship:ship", MT_NEW_END));
-    mt_register(mt_new_va("massive_overload", "ship:ship", MT_NEW_END));
+    mt_create_va(mt_new("ship_drift", NULL),
+        "ship:ship", "dir:int", MT_NEW_END);
+    mt_create_va(mt_new("shipsink", NULL),
+        "ship:ship", MT_NEW_END);
+    mt_create_va(mt_new("massive_overload", NULL),
+        "ship:ship", MT_NEW_END);
 }
 
 static void test_ship_no_overload(CuTest *tc) {
@@ -482,7 +487,8 @@ static void test_follow_ship_msg(CuTest * tc) {
     td->dir = D_NORTHWEST;
     td->age = 2;
 
-    mt_register(mt_new_va("error18", "unit:unit", "region:region", "command:order", MT_NEW_END));
+    mt_create_va(mt_new("error18", NULL),
+        "unit:unit", "region:region", "command:order", MT_NEW_END);
 
     init_order_depr(ord);
     getstrtoken();
diff --git a/src/orderfile.test.c b/src/orderfile.test.c
index 11eb9ea7b..ca98fdeb0 100644
--- a/src/orderfile.test.c
+++ b/src/orderfile.test.c
@@ -64,7 +64,7 @@ static void test_faction_password_bad(CuTest *tc) {
     const char *orders[] = { "ERESSEA 1 password", NULL };
 
     test_setup();
-    mt_register(mt_new_va("wrongpasswd", "password:string", MT_NEW_END));
+    mt_create_va(mt_new("wrongpasswd", NULL), "password:string", MT_NEW_END);
 
     f = test_create_faction(NULL);
     renumber_faction(f, 1);
diff --git a/src/piracy.test.c b/src/piracy.test.c
index 110dc3dcf..096e267b7 100644
--- a/src/piracy.test.c
+++ b/src/piracy.test.c
@@ -30,12 +30,18 @@ static void setup_piracy(void) {
     st_boat = test_create_shiptype("boat");
     st_boat->cargo = 1000;
 
-    mt_register(mt_new_va("piratenovictim", "ship:ship", "unit:unit", "region:region", MT_NEW_END));
-    mt_register(mt_new_va("piratesawvictim", "ship:ship", "unit:unit", "region:region", "dir:int", MT_NEW_END));
-    mt_register(mt_new_va("shipsail", "ship:ship", "from:region", "to:region", MT_NEW_END));
-    mt_register(mt_new_va("shipfly", "ship:ship", "from:region", "to:region", MT_NEW_END));
-    mt_register(mt_new_va("shipnoshore", "ship:ship", "region:region", MT_NEW_END));
-    mt_register(mt_new_va("travel", "unit:unit", "start:region", "end:region", "mode:int", "regions:regions", MT_NEW_END));
+    mt_create_va(mt_new("piratenovictim", NULL),
+        "ship:ship", "unit:unit", "region:region", MT_NEW_END);
+    mt_create_va(mt_new("piratesawvictim", NULL),
+        "ship:ship", "unit:unit", "region:region", "dir:int", MT_NEW_END);
+    mt_create_va(mt_new("shipsail", NULL),
+        "ship:ship", "from:region", "to:region", MT_NEW_END);
+    mt_create_va(mt_new("shipfly", NULL),
+        "ship:ship", "from:region", "to:region", MT_NEW_END);
+    mt_create_va(mt_new("shipnoshore", NULL),
+        "ship:ship", "region:region", MT_NEW_END);
+    mt_create_va(mt_new("travel", NULL),
+        "unit:unit", "start:region", "end:region", "mode:int", "regions:regions", MT_NEW_END);
 }
 
 static void setup_pirate(unit **pirate, int p_r_flags, int p_rc_flags, const char *p_shiptype,
diff --git a/src/renumber.test.c b/src/renumber.test.c
index f176cc3d2..98ca9b48b 100644
--- a/src/renumber.test.c
+++ b/src/renumber.test.c
@@ -38,7 +38,7 @@ static void test_renumber_faction_duplicate(CuTest *tc) {
     const struct locale *lang;
 
     test_setup_ex(tc);
-    mt_register(mt_new_va("renumber_inuse", "id:int", MT_NEW_END));
+    mt_create_va(mt_new("renumber_inuse", NULL), "id:int", MT_NEW_END);
     f2 = test_create_faction(NULL);
     u = test_create_unit(f = test_create_faction(NULL), test_create_region(0, 0, NULL));
     no = f->no;
diff --git a/src/report.c b/src/report.c
index 00089421a..4aee1eb2c 100644
--- a/src/report.c
+++ b/src/report.c
@@ -714,16 +714,17 @@ static void
 rp_messages(struct stream *out, message_list * msgs, faction * viewer, int indent,
     bool categorized)
 {
-    nrsection *section;
-
-    if (!msgs)
+    int i;
+    if (!msgs) {
         return;
-    for (section = sections; section; section = section->next) {
+    }
+    for (i = 0; i != MAXSECTIONS && sections[i]; ++i) {
+        const char * section = sections[i];
         int k = 0;
         struct mlist *m = msgs->begin;
         while (m) {
             /* messagetype * mt = m->type; */
-            if (!categorized || strcmp(nrt_section(m->msg->type), section->name) == 0) {
+            if (!categorized || strcmp(m->msg->type->section, section) == 0) {
                 char lbuf[8192];
 
                 if (!k && categorized) {
@@ -731,14 +732,14 @@ rp_messages(struct stream *out, message_list * msgs, faction * viewer, int inden
                     char cat_identifier[24];
 
                     newline(out);
-                    sprintf(cat_identifier, "section_%s", section->name);
+                    sprintf(cat_identifier, "section_%s", section);
                     section_title = LOC(viewer->locale, cat_identifier);
                     if (section_title) {
                         centre(out, section_title, true);
                         newline(out);
                     }
                     else {
-                        log_error("no title defined for section %s in locale %s", section->name, locale_name(viewer->locale));
+                        log_error("no title defined for section %s in locale %s", section, locale_name(viewer->locale));
                     }
                     k = 1;
                 }
diff --git a/src/spells.test.c b/src/spells.test.c
index dc0644ecc..e6150cb46 100644
--- a/src/spells.test.c
+++ b/src/spells.test.c
@@ -130,8 +130,10 @@ static void test_view_reality(CuTest *tc) {
 
     test_setup();
     setup_spells();
-    mt_register(mt_new_va("spell_astral_only", "unit:unit", "region:region", "command:order", MT_NEW_END));
-    mt_register(mt_new_va("viewreality_effect", "unit:unit", MT_NEW_END));
+    mt_create_va(mt_new("spell_astral_only", NULL),
+        "unit:unit", "region:region", "command:order", MT_NEW_END);
+    mt_create_va(mt_new("viewreality_effect", NULL),
+        "unit:unit", MT_NEW_END);
     r = test_create_region(0, 0, NULL);
     ra = test_create_region(real2tp(r->x), real2tp(r->y), NULL);
     ra->_plane = get_astralplane();
diff --git a/src/spells/flyingship.test.c b/src/spells/flyingship.test.c
index 4440c5fdf..1b1c4d7a1 100644
--- a/src/spells/flyingship.test.c
+++ b/src/spells/flyingship.test.c
@@ -29,7 +29,8 @@ static void test_flyingship(CuTest * tc)
     ship *sh1, *sh2;
 
     test_setup();
-    mt_register(mt_new_va("flying_ship_result", "mage:unit", "ship:ship", MT_NEW_END));
+    mt_create_va(mt_new("flying_ship_result", NULL),
+        "mage:unit", "ship:ship", MT_NEW_END);
 
     par.param = &par_data_ptr;
     par_data.typ = SPP_SHIP;
diff --git a/src/spells/magicresistance.test.c b/src/spells/magicresistance.test.c
index 86a66bc0e..cbfdeb4af 100644
--- a/src/spells/magicresistance.test.c
+++ b/src/spells/magicresistance.test.c
@@ -29,7 +29,8 @@ static void test_magicresistance_unit(CuTest *tc) {
     curse *c;
 
     test_setup();
-    mt_register(mt_new_va("magicresistance_unit", "unit:unit", "id:int", MT_NEW_END));
+    mt_create_va(mt_new("magicresistance_unit", NULL),
+        "unit:unit", "id:int", MT_NEW_END);
     r = test_create_plain(0, 0);
     f1 = test_create_faction(NULL);
     u1 = test_create_unit(f1, r);
@@ -57,7 +58,8 @@ static void test_magicresistance_building(CuTest *tc) {
     curse *c;
 
     test_setup();
-    mt_register(mt_new_va("magicresistance_building", "building:building", "id:int", MT_NEW_END));
+    mt_create_va(mt_new("magicresistance_building", NULL),
+        "building:building", "id:int", MT_NEW_END);
     r = test_create_plain(0, 0);
     f1 = test_create_faction(NULL);
     u1 = test_create_unit(f1, r);
diff --git a/src/spy.test.c b/src/spy.test.c
index 3c4503c98..ed10c4b7e 100644
--- a/src/spy.test.c
+++ b/src/spy.test.c
@@ -33,19 +33,32 @@ typedef struct {
 } spy_fixture;
 
 static void setup_spy(spy_fixture *fix) {
-    mt_register(mt_new_va("spyreport", "spy:unit", "target:unit", "status:int", MT_NEW_END));
-    mt_register(mt_new_va("spyreport_mage", "spy:unit", "target:unit", "type:int", MT_NEW_END));
-    mt_register(mt_new_va("spyreport_faction", "spy:unit", "target:unit", "faction:faction", MT_NEW_END));
-    mt_register(mt_new_va("spyreport_skills", "spy:unit", "target:unit", "skills:string", MT_NEW_END));
-    mt_register(mt_new_va("spyreport_items", "spy:unit", "target:unit", "items:items", MT_NEW_END));
-    mt_register(mt_new_va("destroy_ship_0", "unit:unit", "ship:ship", MT_NEW_END));
-    mt_register(mt_new_va("destroy_ship_1", "unit:unit", "ship:ship", MT_NEW_END));
-    mt_register(mt_new_va("destroy_ship_2", "unit:unit", "ship:ship", MT_NEW_END));
-    mt_register(mt_new_va("destroy_ship_3", "ship:ship", MT_NEW_END));
-    mt_register(mt_new_va("destroy_ship_4", "ship:ship", MT_NEW_END));
-    mt_register(mt_new_va("sink_msg", "ship:ship", "region:region", MT_NEW_END));
-    mt_register(mt_new_va("sink_lost_msg", "unit:unit", "region:region", "dead:int", MT_NEW_END));
-    mt_register(mt_new_va("sink_saved_msg", "unit:unit", "region:region", MT_NEW_END));
+    mt_create_va(mt_new("spyreport", NULL),
+        "spy:unit", "target:unit", "status:int", MT_NEW_END);
+    mt_create_va(mt_new("spyreport_mage", NULL),
+        "spy:unit", "target:unit", "type:int", MT_NEW_END);
+    mt_create_va(mt_new("spyreport_faction", NULL),
+        "spy:unit", "target:unit", "faction:faction", MT_NEW_END);
+    mt_create_va(mt_new("spyreport_skills", NULL),
+        "spy:unit", "target:unit", "skills:string", MT_NEW_END);
+    mt_create_va(mt_new("spyreport_items", NULL),
+        "spy:unit", "target:unit", "items:items", MT_NEW_END);
+    mt_create_va(mt_new("destroy_ship_0", NULL),
+        "unit:unit", "ship:ship", MT_NEW_END);
+    mt_create_va(mt_new("destroy_ship_1", NULL), 
+        "unit:unit", "ship:ship", MT_NEW_END);
+    mt_create_va(mt_new("destroy_ship_2", NULL), 
+        "unit:unit", "ship:ship", MT_NEW_END);
+    mt_create_va(mt_new("destroy_ship_3", NULL),
+        "ship:ship", MT_NEW_END);
+    mt_create_va(mt_new("destroy_ship_4", NULL),
+        "ship:ship", MT_NEW_END);
+    mt_create_va(mt_new("sink_msg", NULL), 
+        "ship:ship", "region:region", MT_NEW_END);
+    mt_create_va(mt_new("sink_lost_msg", NULL), 
+        "unit:unit", "region:region", "dead:int", MT_NEW_END);
+    mt_create_va(mt_new("sink_saved_msg", NULL),
+        "unit:unit", "region:region", MT_NEW_END);
 
     if (fix) {
         fix->r = test_create_region(0, 0, NULL);
diff --git a/src/study.test.c b/src/study.test.c
index 46722c0f6..c1d0b0841 100644
--- a/src/study.test.c
+++ b/src/study.test.c
@@ -58,9 +58,12 @@ typedef struct {
 } study_fixture;
 
 static void setup_study(void) {
-    mt_register(mt_new_va("studycost", "unit:unit", "region:region", "cost:int", "skill:int", MT_NEW_END));
-    mt_register(mt_new_va("teach_teacher", "teacher:unit", "student:unit", "skill:int", "level:int", MT_NEW_END));
-    mt_register(mt_new_va("teach_student", "teacher:unit", "student:unit", "skill:int", MT_NEW_END));
+    mt_create_va(mt_new("studycost", NULL),
+        "unit:unit", "region:region", "cost:int", "skill:int", MT_NEW_END);
+    mt_create_va(mt_new("teach_teacher", NULL),
+        "teacher:unit", "student:unit", "skill:int", "level:int", MT_NEW_END);
+    mt_create_va(mt_new("teach_student", NULL),
+        "teacher:unit", "student:unit", "skill:int", MT_NEW_END);
 }
 
 static void setup_locale(struct locale *lang) {
@@ -218,7 +221,8 @@ static void test_academy_building(CuTest *tc) {
     message * msg;
 
     test_setup();
-    mt_register(mt_new_va("teach_asgood", "unit:unit", "region:region", "command:order", "student:unit", MT_NEW_END));
+    mt_create_va(mt_new("teach_asgood", NULL),
+        "unit:unit", "region:region", "command:order", "student:unit", MT_NEW_END);
 
     random_source_inject_constant(0.0);
     init_resources();
@@ -636,8 +640,10 @@ static void test_teach_message(CuTest *tc) {
     teaching_info *teach;
 
     test_setup();
-    mt_register(mt_new_va("teach_teacher", "teacher:unit", "student:unit", "skill:int", "level:int", MT_NEW_END));
-    mt_register(mt_new_va("teach_student", "teacher:unit", "student:unit", "skill:int", MT_NEW_END));
+    mt_create_va(mt_new("teach_teacher", NULL),
+        "teacher:unit", "student:unit", "skill:int", "level:int", MT_NEW_END);
+    mt_create_va(mt_new("teach_student", NULL),
+        "teacher:unit", "student:unit", "skill:int", MT_NEW_END);
     init_resources();
     u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
     scale_number(u, 20);
diff --git a/src/tests.c b/src/tests.c
index 306148af2..09f533a9f 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -246,9 +246,12 @@ static void test_reset(void) {
     }
     random_source_reset();
 
-    mt_register(mt_new_va("changepasswd", "value:string", MT_NEW_END));
-    mt_register(mt_new_va("starvation", "unit:unit", "region:region", "dead:int", "live:int", MT_NEW_END));
-    mt_register(mt_new_va("malnourish", "unit:unit", "region:region", MT_NEW_END));
+    mt_create_va(mt_new("changepasswd", NULL),
+        "value:string", MT_NEW_END);
+    mt_create_va(mt_new("starvation", NULL),
+        "unit:unit", "region:region", "dead:int", "live:int", MT_NEW_END);
+    mt_create_va(mt_new("malnourish", NULL),
+        "unit:unit", "region:region", MT_NEW_END);
 
     if (errno) {
         int error = errno;
diff --git a/src/triggers/shock.test.c b/src/triggers/shock.test.c
index dad675e64..43b8d394b 100644
--- a/src/triggers/shock.test.c
+++ b/src/triggers/shock.test.c
@@ -12,7 +12,8 @@
 #include <CuTest.h>
 
 static void shock_setup(void) {
-    mt_register(mt_new_va("shock", "mage:unit", "reason:string", MT_NEW_END));
+    mt_create_va(mt_new("shock", NULL),
+        "mage:unit", "reason:string", MT_NEW_END);
 }
 
 static void test_shock(CuTest *tc) {
diff --git a/src/util/message.c b/src/util/message.c
index 71795cfc7..0f8b7cc36 100644
--- a/src/util/message.c
+++ b/src/util/message.c
@@ -60,26 +60,34 @@ arg_type *find_argtype(const char *name)
     return NULL;
 }
 
-message_type *mt_new(const char *name, const char *args[])
+static unsigned int mt_id(const message_type * mtype)
+{
+    unsigned int key = 0;
+    size_t i = strlen(mtype->name);
+
+    while (i > 0) {
+        /* TODO: why not use str_hash? */
+        key = (mtype->name[--i] + key * 37);
+    }
+    return key % 0x7FFFFFFF;
+}
+
+#define MT_MAXHASH 1021
+static selist *messagetypes[MT_MAXHASH];
+
+message_type *mt_create(message_type * mtype, const char *args[])
 {
     int nparameters = 0;
-    message_type *mtype;
+    unsigned int hash = str_hash(mtype->name) % MT_MAXHASH;
+    selist **qlp = messagetypes + hash;
 
-    assert(name != NULL);
-    if (name == NULL) {
-        log_error("Trying to create message_type with name=0x0\n");
-        return NULL;
-    }
     if (args != NULL) {
         /* count the number of parameters */
         while (args[nparameters]) ++nparameters;
     }
-    mtype = (message_type *)malloc(sizeof(message_type));
-    mtype->key = 0;
-    mtype->name = str_strdup(name);
-    mtype->nparameters = nparameters;
     if (nparameters > 0) {
         int i;
+        mtype->nparameters = nparameters;
         mtype->pnames = (char **)malloc(sizeof(char *) * nparameters);
         mtype->types = (arg_type **)malloc(sizeof(arg_type *) * nparameters);
         for (i = 0; args[i]; ++i) {
@@ -103,20 +111,38 @@ message_type *mt_new(const char *name, const char *args[])
             }
         }
     }
-    else {
-        mtype->pnames = NULL;
-        mtype->types = NULL;
+    if (selist_set_insert(qlp, mtype, NULL)) {
+        mtype->key = mt_id(mtype);
     }
     return mtype;
 }
 
-message_type *mt_new_va(const char *name, ...)
+message_type *mt_new(const char *name, const char *section)
+{
+    message_type *mtype;
+
+    assert(name != NULL);
+    if (name == NULL) {
+        log_error("Trying to create message_type with name=0x0\n");
+        return NULL;
+    }
+    mtype = (message_type *)malloc(sizeof(message_type));
+    mtype->key = 0;
+    mtype->name = str_strdup(name);
+    mtype->section = section;
+    mtype->nparameters = 0;
+    mtype->pnames = NULL;
+    mtype->types = NULL;
+    return mtype;
+}
+
+message_type *mt_create_va(message_type *mtype, ...)
 {
     const char *args[16];
     int i = 0;
     va_list marker;
 
-    va_start(marker, name);
+    va_start(marker, mtype);
     for (;;) {
         const char *c = va_arg(marker, const char *);
         args[i++] = c;
@@ -124,8 +150,8 @@ message_type *mt_new_va(const char *name, ...)
             break;
     }
     va_end(marker);
-    args[i] = 0;
-    return mt_new(name, args);
+    args[i] = NULL;
+    return mt_create(mtype, args);
 }
 
 static variant copy_arg(const arg_type * atype, variant data)
@@ -165,9 +191,6 @@ message *msg_create(const struct message_type *mtype, variant args[])
     return msg;
 }
 
-#define MT_MAXHASH 1021
-static selist *messagetypes[MT_MAXHASH];
-
 static void mt_free(void *val) {
     message_type *mtype = (message_type *)val;
     int i;
@@ -205,29 +228,6 @@ const message_type *mt_find(const char *name)
     return 0;
 }
 
-static unsigned int mt_id(const message_type * mtype)
-{
-    unsigned int key = 0;
-    size_t i = strlen(mtype->name);
-
-    while (i > 0) {
-        /* TODO: why not use str_hash? */
-        key = (mtype->name[--i] + key * 37);
-    }
-    return key % 0x7FFFFFFF;
-}
-
-const message_type *mt_register(message_type * type)
-{
-    unsigned int hash = str_hash(type->name) % MT_MAXHASH;
-    selist **qlp = messagetypes + hash;
-
-    if (selist_set_insert(qlp, type, NULL)) {
-        type->key = mt_id(type);
-    }
-    return type;
-}
-
 void msg_free(message * msg)
 {
     int i;
diff --git a/src/util/message.h b/src/util/message.h
index 7521b8e24..41d58b448 100644
--- a/src/util/message.h
+++ b/src/util/message.h
@@ -29,6 +29,7 @@ extern "C" {
     typedef struct message_type {
         unsigned int key;
         char *name;
+        const char *section;
         int nparameters;
         char **pnames;
         struct arg_type ** types;
@@ -43,8 +44,6 @@ extern "C" {
     void message_done(void);
 
     void mt_clear(void);
-    struct message_type *mt_new(const char *name, const char *args[]);
-    struct message_type *mt_new_va(const char *name, ...);
 #define MT_NEW_END ((const char *)0)
     /* mt_new("simple_sentence", "subject:string", "predicate:string",
      *        "object:string", "lang:locale", MT_NEW_END); */
@@ -59,8 +58,10 @@ extern "C" {
 
     const char *mt_name(const struct message_type *mtype);
 
+    struct message_type *mt_new(const char *name, const char *section);
     /** message_type registry (optional): **/
-    const struct message_type *mt_register(struct message_type *);
+    struct message_type *mt_create(struct message_type *, const char *args[]);
+    struct message_type *mt_create_va(struct message_type *, ...);
     const struct message_type *mt_find(const char *);
 
     void register_argtype(const char *name, void(*free_arg) (variant),
diff --git a/src/util/message.test.c b/src/util/message.test.c
index 4b00b4006..df8c75126 100644
--- a/src/util/message.test.c
+++ b/src/util/message.test.c
@@ -8,8 +8,7 @@ static void test_mt_new(CuTest *tc)
 {
     message_type *mt;
     test_setup();
-    mt = mt_new_va("test", "name:string", "number:int", MT_NEW_END);
-    mt_register(mt);
+    mt = mt_create_va(mt_new("test", NULL), "name:string", "number:int", MT_NEW_END);
     CuAssertPtrNotNull(tc, mt);
     CuAssertStrEquals(tc, "test", mt->name);
     CuAssertIntEquals(tc, 2, mt->nparameters);
diff --git a/src/util/nrmessage.c b/src/util/nrmessage.c
index 9461e11c5..047d3565b 100644
--- a/src/util/nrmessage.c
+++ b/src/util/nrmessage.c
@@ -30,7 +30,6 @@ typedef struct nrmessage_type {
     const struct message_type *mtype;
     char *vars;
     struct nrmessage_type *next;
-    const char *section;
 } nrmessage_type;
 
 #define NRT_MAXHASH 1021
@@ -66,41 +65,44 @@ static nrmessage_type *nrt_find(const struct message_type * mtype)
     return found;
 }
 
-nrsection *sections;
+char *sections[MAXSECTIONS];
 
-const nrsection *section_find(const char *name)
+const char *section_find(const char *name)
 {
-    nrsection **mcp = &sections;
-    if (name == NULL)
+    int i;
+
+    if (name == NULL) {
         return NULL;
-    for (; *mcp; mcp = &(*mcp)->next) {
-        nrsection *mc = *mcp;
-        if (!strcmp(mc->name, name))
-            break;
     }
-    return *mcp;
+
+    for (i = 0; i != MAXSECTIONS && sections[i]; ++i) {
+        if (strcmp(sections[i], name) == 0) {
+            return sections[i];
+        }
+    }
+    return NULL;
 }
 
-const nrsection *section_add(const char *name)
-{
-    nrsection **mcp = &sections;
-    if (name == NULL)
+const char *section_add(const char *name) {
+    int i;
+    if (name == NULL) {
         return NULL;
-    for (; *mcp; mcp = &(*mcp)->next) {
-        nrsection *mc = *mcp;
-        if (!strcmp(mc->name, name))
-            break;
     }
-    if (!*mcp) {
-        nrsection *mc = calloc(sizeof(nrsection), 1);
-        mc->name = str_strdup(name);
-        *mcp = mc;
+    for (i = 0; i != MAXSECTIONS && sections[i]; ++i) {
+        if (strcmp(sections[i], name) == 0) {
+            return sections[i];
+        }
     }
-    return *mcp;
+    assert(i < MAXSECTIONS);
+    assert(sections[i] == NULL);
+    if (i + 1 < MAXSECTIONS) {
+        sections[i + 1] = NULL;
+    }
+    return sections[i] = str_strdup(name);
 }
 
 void
-nrt_register(const struct message_type *mtype, const char *section)
+nrt_register(const struct message_type *mtype)
 {
     unsigned int hash = mtype->key % NRT_MAXHASH;
     nrmessage_type *nrt = nrtypes[hash];
@@ -118,15 +120,6 @@ nrt_register(const struct message_type *mtype, const char *section)
         nrt = malloc(sizeof(nrmessage_type));
         nrt->mtype = mtype;
         nrt->next = nrtypes[hash];
-        if (section) {
-            const nrsection *s = section_find(section);
-            if (s == NULL) {
-                s = section_add(section);
-            }
-            nrt->section = s->name;
-        }
-        else
-            nrt->section = NULL;
         nrtypes[hash] = nrt;
         *c = '\0';
         for (i = 0; i != mtype->nparameters; ++i) {
@@ -159,12 +152,6 @@ size_t size, const void *userdata)
     return 0;
 }
 
-const char *nrt_section(const struct message_type * mtype)
-{
-    nrmessage_type *nrt = nrt_find(mtype);
-    return nrt ? nrt->section : NULL;
-}
-
 void free_nrmesssages(void) {
     int i;
     for (i = 0; i != NRT_MAXHASH; ++i) {
diff --git a/src/util/nrmessage.h b/src/util/nrmessage.h
index 357e5d5c5..c0d9257aa 100644
--- a/src/util/nrmessage.h
+++ b/src/util/nrmessage.h
@@ -25,19 +25,14 @@ extern "C" {
     struct message_type;
     struct nrmessage_type;
 
-    typedef struct nrsection {
-        char *name;
-        struct nrsection *next;
-    } nrsection;
-
-    extern nrsection *sections;
+#define MAXSECTIONS 8
+    extern char *sections[MAXSECTIONS];
 
     void free_nrmesssages(void);
 
-    void nrt_register(const struct message_type *mtype, const char *section);
+    void nrt_register(const struct message_type *mtype);
     const char *nrt_string(const struct message_type *mtype,
             const struct locale *lang);
-    const char *nrt_section(const struct message_type *mtype);
 
     size_t nr_render(const struct message *msg, const struct locale *lang,
         char *buffer, size_t size, const void *userdata);
diff --git a/src/volcano.test.c b/src/volcano.test.c
index 8a8358c1c..c62febc0d 100644
--- a/src/volcano.test.c
+++ b/src/volcano.test.c
@@ -20,7 +20,8 @@ static void test_volcano_update(CuTest *tc) {
     const struct terrain_type *t_volcano, *t_active;
     
     test_setup();
-    mt_register(mt_new_va("volcanostopsmoke", "region:region", MT_NEW_END));
+    mt_create_va(mt_new("volcanostopsmoke", NULL),
+        "region:region", MT_NEW_END);
     t_volcano = test_create_terrain("volcano", LAND_REGION);
     t_active = test_create_terrain("activevolcano", LAND_REGION);
     r = test_create_region(0, 0, t_active);
@@ -42,9 +43,12 @@ static void test_volcano_outbreak(CuTest *tc) {
     const struct terrain_type *t_volcano, *t_active;
     
     test_setup();
-    mt_register(mt_new_va("volcanooutbreak", "regionv:region", "regionn:region", MT_NEW_END));
-    mt_register(mt_new_va("volcanooutbreaknn", "region:region", MT_NEW_END));
-    mt_register(mt_new_va("volcano_dead", "unit:unit", "region:region", "dead:int", MT_NEW_END));
+    mt_create_va(mt_new("volcanooutbreak", NULL), 
+        "regionv:region", "regionn:region", MT_NEW_END);
+    mt_create_va(mt_new("volcanooutbreaknn", NULL),
+        "region:region", MT_NEW_END);
+    mt_create_va(mt_new("volcano_dead", NULL),
+        "unit:unit", "region:region", "dead:int", MT_NEW_END);
     t_volcano = test_create_terrain("volcano", LAND_REGION);
     t_active = test_create_terrain("activevolcano", LAND_REGION);
     r = test_create_region(0, 0, t_active);
diff --git a/src/wormhole.test.c b/src/wormhole.test.c
index e275d4d67..b8baaa79a 100644
--- a/src/wormhole.test.c
+++ b/src/wormhole.test.c
@@ -19,10 +19,14 @@ void sort_wormhole_regions(selist *rlist, region **match, int count);
 void make_wormholes(region **match, int count, const building_type *bt_wormhole);
 
 static void setup_wormholes(void) {
-    mt_register(mt_new_va("wormhole_appear", "region:region", MT_NEW_END));
-    mt_register(mt_new_va("wormhole_dissolve", "region:region", MT_NEW_END));
-    mt_register(mt_new_va("wormhole_exit", "unit:unit", "region:region", MT_NEW_END));
-    mt_register(mt_new_va("wormhole_requirements", "unit:unit", "region:region", MT_NEW_END));
+    mt_create_va(mt_new("wormhole_appear", NULL),
+        "region:region", MT_NEW_END);
+    mt_create_va(mt_new("wormhole_dissolve", NULL),
+        "region:region", MT_NEW_END);
+    mt_create_va(mt_new("wormhole_exit", NULL),
+        "unit:unit", "region:region", MT_NEW_END);
+    mt_create_va(mt_new("wormhole_requirements", NULL),
+        "unit:unit", "region:region", MT_NEW_END);
 }
 
 static void test_make_wormholes(CuTest *tc) {
diff --git a/src/xmlreader.c b/src/xmlreader.c
index 88ab51237..8ba33db84 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -1304,18 +1304,28 @@ static int parse_messages(xmlDocPtr doc)
         xmlXPathFreeObject(result);
 
         /* add the messagetype */
+        propSection = xmlGetProp(node, BAD_CAST "section");
+        if (propSection == NULL) {
+            propSection = BAD_CAST default_section;
+        }
+
         propValue = xmlGetProp(node, BAD_CAST "name");
         mtype = mt_find((const char *)propValue);
         if (mtype == NULL) {
-            mtype = mt_register(mt_new((const char *)propValue, (const char **)argv));
+            mtype = mt_create(mt_new((const char *)propValue, (const char *)propSection), (const char **)argv);
         }
         else {
             assert(argv != NULL || !"cannot redefine arguments of message now");
         }
         xmlFree(propValue);
 
-        /* register the type for the CR */
+        if (propSection != BAD_CAST default_section) {
+            xmlFree(propSection);
+        }
+
+        /* register the type for CR and NR */
         crt_register(mtype);
+        nrt_register(mtype);
 
         /* let's clean up the mess */
         if (argv != NULL) {
@@ -1323,16 +1333,6 @@ static int parse_messages(xmlDocPtr doc)
                 free(argv[k]);
             free(argv);
         }
-
-        propSection = xmlGetProp(node, BAD_CAST "section");
-        if (propSection == NULL) {
-            propSection = BAD_CAST default_section;
-        }
-        nrt_register(mtype, (const char *)propSection);
-
-        if (propSection != BAD_CAST default_section) {
-            xmlFree(propSection);
-        }
     }
 
     xmlXPathFreeObject(messages);

From 6b0f75339f0c31402277d59eaea5b94e9fc11015 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 18 May 2018 20:42:22 +0200
Subject: [PATCH 51/59] message parsing from exparse is working, but allocates
 too much.

---
 src/exparse.c              | 88 +++++++++++++++++++++++++++++---------
 src/kernel/messages.test.c |  4 +-
 src/util/message.c         | 23 ++++++----
 src/util/message.h         |  8 ++--
 src/xmlreader.c            | 16 ++++---
 5 files changed, 97 insertions(+), 42 deletions(-)

diff --git a/src/exparse.c b/src/exparse.c
index e323bb74c..271443c05 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -17,6 +17,8 @@
 #include "util/functions.h"
 #include "util/log.h"
 #include "util/message.h"
+#include "util/crmessage.h"
+#include "util/nrmessage.h"
 #include "util/strings.h"
 
 #include <expat.h>
@@ -285,8 +287,56 @@ static void handle_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **at
     wtype->flags = flags;
 }
 
-static void XMLCALL start_messages(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+static int msg_nargs;
+static char * msg_args[MSG_MAXARGS];
+
+static void end_messages(parseinfo *pi, const XML_Char *el) {
     if (xml_strcmp(el, "message") == 0) {
+        int i;
+        struct message_type *mtype = (struct message_type *)pi->object;
+        assert(mtype);
+        assert(msg_nargs < MSG_MAXARGS);
+        mt_create(mtype, (const char **)msg_args, msg_nargs);
+        /* register the type for CR and NR */
+        crt_register(mtype);
+        nrt_register(mtype);
+
+        for (i = 0; i != msg_nargs; ++i) {
+            free(msg_args[i]);
+            msg_args[i] = NULL;
+        }
+        msg_nargs = 0;
+    }
+    else if (xml_strcmp(el, "messages") == 0) {
+        pi->type = EXP_UNKNOWN;
+    }
+}
+
+static void start_messages(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+    if (xml_strcmp(el, "arg") == 0) {
+        int i;
+        const XML_Char *name = NULL, *type = NULL;
+
+        assert(msg_nargs < MSG_MAXARGS);
+        for (i = 0; attr[i]; i += 2) {
+            const XML_Char *key = attr[i], *val = attr[i + 1];
+            if (xml_strcmp(key, "name") == 0) {
+                name = val;
+            }
+            else if (xml_strcmp(key, "type") == 0) {
+                type = val;
+            }
+            else {
+                handle_bad_input(pi, el, key);
+            }
+        }
+        if (name && type) {
+            char zBuffer[128];
+            sprintf(zBuffer, "%s:%s", name, type);
+            msg_args[msg_nargs++] = str_strdup(zBuffer);
+        }
+    }
+    else if (xml_strcmp(el, "message") == 0) {
         const XML_Char *name = NULL, *section = NULL;
         int i;
         for (i = 0; attr[i]; i += 2) {
@@ -297,18 +347,24 @@ static void XMLCALL start_messages(parseinfo *pi, const XML_Char *el, const XML_
             else if (xml_strcmp(key, "section") == 0) {
                 section = val;
             }
+            else {
+                handle_bad_input(pi, el, key);
+            }
         }
         if (name) {
-            pi->object = mt_new(name, NULL);
+            pi->object = mt_new(name, section);
         }
     }
+    else if (xml_strcmp(el, "type") != 0 && xml_strcmp(el, "text") != 0) {
+        handle_bad_input(pi, el, NULL);
+    }
 }
 
 #define MAX_COMPONENTS 8
 static spell_component components[MAX_COMPONENTS];
 static int ncomponents;
 
-static void XMLCALL start_spells(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+static void start_spells(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     const char *flag_names[] = {
         "far", "variable", "ocean", "ship", "los", 
         "unittarget", "shiptarget", "buildingtarget", "regiontarget", "globaltarget", NULL };
@@ -390,7 +446,7 @@ static void XMLCALL start_spells(parseinfo *pi, const XML_Char *el, const XML_Ch
     }
 }
 
-static void XMLCALL start_spellbooks(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+static void start_spellbooks(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     spellbook * sb = (spellbook *)pi->object;
     if (xml_strcmp(el, "spellbook") == 0) {
         const XML_Char *name = attr_get(attr, "name");
@@ -430,7 +486,7 @@ static void XMLCALL start_spellbooks(parseinfo *pi, const XML_Char *el, const XM
     }
 }
 
-static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+static void start_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     resource_type *rtype = (resource_type *)pi->object;
 
     assert(rtype && rtype->wtype);
@@ -791,7 +847,7 @@ static void start_resources(parseinfo *pi, const XML_Char *el, const XML_Char **
     }
 }
 
-static void XMLCALL start_ships(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+static void start_ships(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     const char *flag_names[] = { "opensea", "fly", "nocoast", "speedy", NULL };
     if (xml_strcmp(el, "ship") == 0) {
         const XML_Char *name;
@@ -899,7 +955,7 @@ static void XMLCALL start_ships(parseinfo *pi, const XML_Char *el, const XML_Cha
 static int nattacks;
 static int nfamiliars;
 
-static void XMLCALL start_races(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+static void start_races(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     race *rc = (race *)pi->object;
     const char *flag_names[] = {
         "playerrace", "killpeasants", "scarepeasants", "!cansteal",
@@ -1116,7 +1172,7 @@ static void XMLCALL start_races(parseinfo *pi, const XML_Char *el, const XML_Cha
     }
 }
 
-static void XMLCALL start_buildings(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
+static void start_buildings(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
     const char *flag_names[] = { "nodestroy", "nobuild", "unique", "decay", "magic", "namechange", "fort", "oneperturn", NULL };
     if (xml_strcmp(el, "building") == 0) {
         const XML_Char *name;
@@ -1427,6 +1483,9 @@ static void XMLCALL handle_end(void *data, const XML_Char *el) {
     case EXP_SPELLS:
         end_spells(pi, el);
         break;
+    case EXP_MESSAGES:
+        end_messages(pi, el);
+        break;
     default:
         if (pi->depth == 1) {
             pi->object = NULL;
@@ -1444,18 +1503,6 @@ static void XMLCALL handle_end(void *data, const XML_Char *el) {
     }
 }
 
-static void XMLCALL handle_data(void *data, const XML_Char *xs, int len) {
-    parseinfo *pi = (parseinfo *)data;
-    if (len > 0) {
-        if (pi->type == EXP_MESSAGES && pi->depth == 4) {
-            size_t bytes = (size_t)len;
-            pi->cdata = realloc(pi->cdata, pi->clength + bytes);
-            memcpy(pi->cdata + pi->clength, xs, bytes);
-            pi->clength = pi->clength + bytes;
-        }
-    }
-}
-
 int exparse_readfile(const char * filename) {
     XML_Parser xp;
     FILE *F;
@@ -1469,7 +1516,6 @@ int exparse_readfile(const char * filename) {
     }
     xp = XML_ParserCreate("UTF-8");
     XML_SetElementHandler(xp, handle_start, handle_end);
-    XML_SetCharacterDataHandler(xp, handle_data);
     XML_SetUserData(xp, &pi);
     memset(&pi, 0, sizeof(pi));
     for (;;) {
diff --git a/src/kernel/messages.test.c b/src/kernel/messages.test.c
index 961d2e63a..c017f6ec1 100644
--- a/src/kernel/messages.test.c
+++ b/src/kernel/messages.test.c
@@ -25,7 +25,7 @@ void test_message(CuTest *tc) {
     message_type *mtype;
 
     test_setup();
-    mtype = mt_create(mt_new("custom", NULL), NULL);
+    mtype = mt_create(mt_new("custom", NULL), NULL, 0);
     CuAssertPtrEquals(tc, mtype, (void *)mt_find("custom"));
     CuAssertIntEquals(tc, 0, mtype->nparameters);
     CuAssertPtrEquals(tc, NULL, (void *)mtype->pnames);
@@ -51,7 +51,7 @@ static void test_merge_split(CuTest *tc) {
     message *msg;
 
     test_setup();
-    mtype = mt_create(mt_new("custom", NULL), NULL);
+    mtype = mt_create(mt_new("custom", NULL), NULL, 0);
     add_message(&mlist, msg = msg_message(mtype->name, ""));
     msg_release(msg);
     add_message(&append, msg = msg_message(mtype->name, ""));
diff --git a/src/util/message.c b/src/util/message.c
index 0f8b7cc36..b01993098 100644
--- a/src/util/message.c
+++ b/src/util/message.c
@@ -75,15 +75,22 @@ static unsigned int mt_id(const message_type * mtype)
 #define MT_MAXHASH 1021
 static selist *messagetypes[MT_MAXHASH];
 
-message_type *mt_create(message_type * mtype, const char *args[])
-{
-    int nparameters = 0;
+static void mt_register(message_type * mtype) {
     unsigned int hash = str_hash(mtype->name) % MT_MAXHASH;
     selist **qlp = messagetypes + hash;
 
-    if (args != NULL) {
+    if (selist_set_insert(qlp, mtype, NULL)) {
+        mtype->key = mt_id(mtype);
+    }
+}
+
+message_type *mt_create(message_type * mtype, const char *args[], int nparameters)
+{
+    if (args != NULL && args[nparameters]) {
         /* count the number of parameters */
-        while (args[nparameters]) ++nparameters;
+        do {
+            ++nparameters;
+        } while (args[nparameters]);
     }
     if (nparameters > 0) {
         int i;
@@ -111,9 +118,7 @@ message_type *mt_create(message_type * mtype, const char *args[])
             }
         }
     }
-    if (selist_set_insert(qlp, mtype, NULL)) {
-        mtype->key = mt_id(mtype);
-    }
+    mt_register(mtype);
     return mtype;
 }
 
@@ -151,7 +156,7 @@ message_type *mt_create_va(message_type *mtype, ...)
     }
     va_end(marker);
     args[i] = NULL;
-    return mt_create(mtype, args);
+    return mt_create(mtype, args, i - 1);
 }
 
 static variant copy_arg(const arg_type * atype, variant data)
diff --git a/src/util/message.h b/src/util/message.h
index 41d58b448..40cc09086 100644
--- a/src/util/message.h
+++ b/src/util/message.h
@@ -18,6 +18,9 @@
 extern "C" {
 #endif
 
+#define MSG_MAXARGS 8
+#define MT_NEW_END ((const char *)0)
+
     typedef struct arg_type {
         struct arg_type *next;
         variant_type vtype;
@@ -44,9 +47,6 @@ extern "C" {
     void message_done(void);
 
     void mt_clear(void);
-#define MT_NEW_END ((const char *)0)
-    /* mt_new("simple_sentence", "subject:string", "predicate:string",
-     *        "object:string", "lang:locale", MT_NEW_END); */
 
     struct message *msg_create(const struct message_type *type,
         variant args[]);
@@ -60,7 +60,7 @@ extern "C" {
 
     struct message_type *mt_new(const char *name, const char *section);
     /** message_type registry (optional): **/
-    struct message_type *mt_create(struct message_type *, const char *args[]);
+    struct message_type *mt_create(struct message_type *, const char *args[], int nargs);
     struct message_type *mt_create_va(struct message_type *, ...);
     const struct message_type *mt_find(const char *);
 
diff --git a/src/xmlreader.c b/src/xmlreader.c
index 8ba33db84..2decd9cb5 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -1277,7 +1277,7 @@ static int parse_messages(xmlDocPtr doc)
         xmlChar *propSection;
         xmlChar *propValue;
         xmlXPathObjectPtr result;
-        int k;
+        int nargs = 0;
         char **argv = NULL;
         const message_type *mtype;
 
@@ -1285,8 +1285,10 @@ static int parse_messages(xmlDocPtr doc)
         xpath->node = node;
         result = xmlXPathEvalExpression(BAD_CAST "type/arg", xpath);
         if (result->nodesetval && result->nodesetval->nodeNr > 0) {
-            argv = malloc(sizeof(char *) * (result->nodesetval->nodeNr + 1));
-            for (k = 0; k != result->nodesetval->nodeNr; ++k) {
+            int k;
+            nargs = result->nodesetval->nodeNr;
+            argv = malloc(sizeof(char *) * (nargs + 1));
+            for (k = 0; k != nargs; ++k) {
                 xmlNodePtr node = result->nodesetval->nodeTab[k];
                 char zBuffer[128];
                 xmlChar *propName, *propType;
@@ -1299,7 +1301,7 @@ static int parse_messages(xmlDocPtr doc)
                 xmlFree(propType);
                 argv[k] = str_strdup(zBuffer);
             }
-            argv[result->nodesetval->nodeNr] = NULL;
+            argv[nargs] = NULL;
         }
         xmlXPathFreeObject(result);
 
@@ -1312,7 +1314,7 @@ static int parse_messages(xmlDocPtr doc)
         propValue = xmlGetProp(node, BAD_CAST "name");
         mtype = mt_find((const char *)propValue);
         if (mtype == NULL) {
-            mtype = mt_create(mt_new((const char *)propValue, (const char *)propSection), (const char **)argv);
+            mtype = mt_create(mt_new((const char *)propValue, (const char *)propSection), (const char **)argv, nargs);
         }
         else {
             assert(argv != NULL || !"cannot redefine arguments of message now");
@@ -1329,8 +1331,10 @@ static int parse_messages(xmlDocPtr doc)
 
         /* let's clean up the mess */
         if (argv != NULL) {
-            for (k = 0; argv[k] != NULL; ++k)
+            int k;
+            for (k = 0; argv[k] != NULL; ++k) {
                 free(argv[k]);
+            }
             free(argv);
         }
     }

From f5d6e6ac6e2a8bb4cc52c1ad053421ac91236a2a Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 18 May 2018 20:43:22 +0200
Subject: [PATCH 52/59] we do not need xmlreader anymore!

---
 src/xmlreader.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/xmlreader.c b/src/xmlreader.c
index 2decd9cb5..5a11eaf91 100644
--- a/src/xmlreader.c
+++ b/src/xmlreader.c
@@ -1354,8 +1354,6 @@ void register_xmlreader(void)
     xml_register_callback(parse_spellbooks);
     xml_register_callback(parse_spells);
     xml_register_callback(parse_races);
-#endif
-
-
     xml_register_callback(parse_messages);
+#endif
 }

From ce37fd1bb7c77f3f3616973405d9fe7dbc60f8c0 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 18 May 2018 21:14:14 +0200
Subject: [PATCH 53/59] remove libxml2 from dependencies remove the converter,
 that isn't a way we're going.

---
 CMakeLists.txt          |    4 +-
 src/CMakeLists.txt      |   29 +-
 src/bindings.c          |   23 -
 src/convert.c           |   37 --
 src/eressea.c           |    2 -
 src/gmtool.c            |    1 -
 src/jsonconf.c          |   12 +-
 src/kernel/build.c      |    1 -
 src/kernel/config.c     |    6 -
 src/kernel/ship.c       |    1 -
 src/spells.c            |    1 -
 src/util/CMakeLists.txt |    2 -
 src/util/xml.c          |  131 ----
 src/util/xml.h          |   39 --
 src/xmlreader.c         | 1361 ---------------------------------------
 src/xmlreader.h         |   28 -
 16 files changed, 4 insertions(+), 1674 deletions(-)
 delete mode 100644 src/convert.c
 delete mode 100644 src/util/xml.c
 delete mode 100644 src/util/xml.h
 delete mode 100644 src/xmlreader.c
 delete mode 100644 src/xmlreader.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index f73ba04a1..4b91565da 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,8 +50,7 @@ else()
 find_package (SQLite3 REQUIRED QUIET)
 endif()
 
-find_package(EXPAT)
-find_package (LibXml2 REQUIRED)
+find_package(EXPAT REQUIRED)
 find_package (ToLua REQUIRED)
 if (TOLUA_FOUND)
 if (${TOLUA_VERSION_STRING} VERSION_EQUAL "5.2")
@@ -71,6 +70,7 @@ add_subdirectory (process)
 add_subdirectory (src eressea)
 
 install(DIRECTORY etc DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.txt")
+install(DIRECTORY res conf DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.po")
 install(DIRECTORY res conf DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.xml")
 install(DIRECTORY res conf DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.json")
 install(DIRECTORY scripts DESTINATION ${CMAKE_INSTALL_PREFIX} FILES_MATCHING PATTERN "*.lua")
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 21d07e9b2..5b267c0d5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -111,6 +111,7 @@ set (ERESSEA_SRC
   report.c
   steal.c
   economy.c
+  exparse.c
   give.c
   items.c
   laws.c
@@ -127,7 +128,6 @@ set (ERESSEA_SRC
   travelthru.c
   monsters.c
   wormhole.c
-  xmlreader.c
   ${SPELLS_SRC}
   ${RACES_SRC}
   ${ITEMS_SRC}
@@ -139,11 +139,6 @@ set (ERESSEA_SRC
   ${UTIL_SRC}
 )
 
-IF(EXPAT_FOUND)
-set (ERESSEA_SRC ${ERESSEA_SRC} exparse.c)
-ENDIF(EXPAT_FOUND)
-
-
 set(SERVER_SRC
   main.c
   console.c
@@ -187,15 +182,6 @@ target_link_libraries(eressea
   ${INIPARSER_LIBRARIES}
 )
 
-add_executable(convert convert.c)
-target_link_libraries(convert
-  game
-  ${LUA_MATH_LIBRARY}
-  ${STORAGE_LIBRARIES}
-  ${CLIBS_LIBRARIES}
-  ${INIPARSER_LIBRARIES}
-)
-
 set(TESTS_SRC
   test_eressea.c
   tests.c
@@ -235,7 +221,6 @@ set(TESTS_SRC
   volcano.test.c
   vortex.test.c
   wormhole.test.c
-# xmlreader.test.c
   spells/flyingship.test.c
   spells/magicresistance.test.c
   triggers/shock.test.c
@@ -285,18 +270,15 @@ endif(HAVE_STRDUP)
 if (HAVE_LIBBSD)
 target_link_libraries(test_eressea bsd)
 target_link_libraries(eressea bsd)
-target_link_libraries(convert bsd)
 endif (HAVE_LIBBSD)
 
 if (SQLITE3_FOUND)
 include_directories (${SQLITE3_INCLUDE_DIR})
 target_link_libraries(eressea ${SQLITE3_LIBRARIES})
-target_link_libraries(convert ${SQLITE3_LIBRARIES})
 target_link_libraries(test_eressea ${SQLITE3_LIBRARIES})
 add_definitions(-DUSE_SQLITE)
 elseif (DB_FOUND)
 include_directories (${DB_INCLUDE_DIR})
-target_link_libraries(convert ${DB_LIBRARIES})
 target_link_libraries(eressea ${DB_LIBRARIES})
 target_link_libraries(test_eressea ${DB_LIBRARIES})
 add_definitions(-DUSE_DB)
@@ -317,14 +299,5 @@ endif(CURSES_FOUND)
 if (EXPAT_FOUND)
 include_directories (${EXPAT_INCLUDE_DIRS})
 target_link_libraries(eressea ${EXPAT_LIBRARIES})
-target_link_libraries(convert ${EXPAT_LIBRARIES})
 target_link_libraries(test_eressea ${EXPAT_LIBRARIES})
-add_definitions(-DUSE_EXPAT)
 endif (EXPAT_FOUND)
-
-if (LIBXML2_FOUND)
-include_directories (${LIBXML2_INCLUDE_DIR})
-target_link_libraries(eressea ${LIBXML2_LIBRARIES})
-target_link_libraries(convert ${LIBXML2_LIBRARIES})
-target_link_libraries(test_eressea ${LIBXML2_LIBRARIES})
-endif (LIBXML2_FOUND)
diff --git a/src/bindings.c b/src/bindings.c
index 5c6174c75..d72bddac2 100755
--- a/src/bindings.c
+++ b/src/bindings.c
@@ -59,7 +59,6 @@
 #include <util/nrmessage.h>
 #include <util/rand.h>
 #include <util/rng.h>
-#include <util/xml.h>
 
 #include <selist.h>
 #include <storage.h>
@@ -833,33 +832,12 @@ static int tolua_get_spells(lua_State * L)
     return tolua_selist_push(L, "spell_list", "spell", spells);
 }
 
-static int init_data(const char *filename)
-{
-    int l;
-    l = read_xml(filename);
-    reset_locales();
-    if (l) {
-        return l;
-    }
-    if (turn <= 0) {
-        turn = first_turn();
-    }
-    return 0;
-}
-
 static int tolua_equip_newunits(lua_State * L) {
     unit *u = (unit *)tolua_tousertype(L, 1, 0);
     equip_newunits(u);
     return 0;
 }
 
-static int tolua_read_xml(lua_State * L)
-{
-    const char *filename = tolua_tostring(L, 1, "config.xml");
-    lua_pushinteger(L, init_data(filename));
-    return 1;
-}
-
 static int tolua_report_unit(lua_State * L)
 {
     char buffer[512];
@@ -1029,7 +1007,6 @@ int tolua_bindings_open(lua_State * L, const dictionary *inifile)
         tolua_function(L, TOLUA_CAST "set_key", tolua_setkey);
         tolua_function(L, TOLUA_CAST "translate", &tolua_translate);
         tolua_function(L, TOLUA_CAST "spells", tolua_get_spells);
-        tolua_function(L, TOLUA_CAST "read_xml", tolua_read_xml);
         tolua_function(L, TOLUA_CAST "equip_newunits", tolua_equip_newunits);
     } tolua_endmodule(L);
     return 1;
diff --git a/src/convert.c b/src/convert.c
deleted file mode 100644
index 6470c9e32..000000000
--- a/src/convert.c
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <platform.h>
-
-
-#include "xmlreader.h"
-#include <util/xml.h>
-#include <kernel/race.h>
-#include <kernel/rules.h>
-#include <races/races.h>
-
-#include <storage.h>
-
-#include <string.h>
-
-static int usage(void) {
-    return -1;
-}
-
-int main(int argc, char **argv) {
-    const char *mode;
-
-    register_races();
-    register_xmlreader();
-    if (argc < 2) return usage();
-    mode = argv[1];
-    if (strcmp(mode, "rules")==0) {
-        const char *xmlfile;
-        if (argc < 4) return usage();
-        xmlfile = argv[2];
-        read_xml(xmlfile);
-        write_rules("rules.dat");
-        return 0;
-    }
-    if (strcmp(mode, "po")==0) {
-        return 0;
-    }
-    return usage();
-}
diff --git a/src/eressea.c b/src/eressea.c
index 81f19b5a6..bdb20edcc 100644
--- a/src/eressea.c
+++ b/src/eressea.c
@@ -33,7 +33,6 @@
 #include "spells.h"
 #include "vortex.h"
 #include "wormhole.h"
-#include "xmlreader.h"
 
 #include <errno.h>
 #include <stdlib.h>
@@ -80,7 +79,6 @@ void game_init(void)
 
     register_weapons();
     register_xerewards();
-    register_xmlreader();
     register_attributes();
     register_gmcmd();
 
diff --git a/src/gmtool.c b/src/gmtool.c
index d63b93c5c..e13701f6f 100644
--- a/src/gmtool.c
+++ b/src/gmtool.c
@@ -55,7 +55,6 @@
 #include "listbox.h"
 #include "wormhole.h"
 #include "teleport.h"
-#include "xmlreader.h"
 
 #include <storage.h>
 #include <lua.h>
diff --git a/src/jsonconf.c b/src/jsonconf.c
index c91f8a749..fcd6f5c78 100644
--- a/src/jsonconf.c
+++ b/src/jsonconf.c
@@ -39,7 +39,6 @@ without prior permission by the authors of Eressea.
 #include "util/path.h"
 #include "util/pofile.h"
 #include "util/strings.h"
-#include "util/xml.h"
 
 /* game modules */
 #include "direction.h"
@@ -47,9 +46,7 @@ without prior permission by the authors of Eressea.
 #include "move.h"
 #include "prefix.h"
 #include "skill.h"
-#ifdef USE_EXPAT
 #include "exparse.h"
-#endif
 
 /* external libraries */
 #include <cJSON.h>
@@ -1017,14 +1014,7 @@ static int include_xml(const char *uri) {
     char name[PATH_MAX];
     const char *filename = uri_to_file(uri, name, sizeof(name));
     int err;
-#ifdef USE_EXPAT
     err = exparse_readfile(filename);
-    if (err != 0) {
-        err = read_xml(filename);
-    }
-#else
-    err = read_xml(filename);
-#endif
     if (err != 0) {
         log_error("could not parse XML from %s", uri);
     }
@@ -1058,7 +1048,7 @@ static int include_po(const char *uri) {
             if (lang) {
                 int err = pofile_read(filename, add_po_string, lang);
                 if (err < 0) {
-                    log_error("could not parse XML from %s", uri);
+                    log_error("could not parse translations from %s", uri);
                 }
                 return err;
             }
diff --git a/src/kernel/build.c b/src/kernel/build.c
index 45a7d0898..310e4bd43 100644
--- a/src/kernel/build.c
+++ b/src/kernel/build.c
@@ -60,7 +60,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include <util/log.h>
 #include <util/parser.h>
 #include <util/resolve.h>
-#include <util/xml.h>
 
 /* from libc */
 #include <assert.h>
diff --git a/src/kernel/config.c b/src/kernel/config.c
index 54d030b76..8eef66341 100644
--- a/src/kernel/config.c
+++ b/src/kernel/config.c
@@ -66,16 +66,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include <util/strings.h>
 #include <util/translation.h>
 #include <util/umlaut.h>
-#include <util/xml.h>
 
 #include "donations.h"
 #include "guard.h"
 #include "prefix.h"
 
-/* libxml includes */
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
-
 /* external libraries */
 #include <iniparser.h>
 #include <critbit.h>
@@ -559,7 +554,6 @@ void kernel_done(void)
     /* calling this function releases memory assigned to static variables, etc.
      * calling it is optional, e.g. a release server will most likely not do it.
      */
-    xml_done();
     attrib_done();
     item_done();
     message_done();
diff --git a/src/kernel/ship.c b/src/kernel/ship.c
index def6dd1fa..4719945b0 100644
--- a/src/kernel/ship.c
+++ b/src/kernel/ship.c
@@ -42,7 +42,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include <util/log.h>
 #include <util/strings.h>
 #include <util/umlaut.h>
-#include <util/xml.h>
 
 #include <storage.h>
 #include <selist.h>
diff --git a/src/spells.c b/src/spells.c
index bd2c8ea1a..4e98b1a2a 100644
--- a/src/spells.c
+++ b/src/spells.c
@@ -26,7 +26,6 @@
 #include "randenc.h"
 #include "monsters.h"
 #include "teleport.h"
-#include "xmlreader.h"
 
  /* triggers includes */
 #include <triggers/changefaction.h>
diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt
index 19f9b608b..b462d2bd3 100644
--- a/src/util/CMakeLists.txt
+++ b/src/util/CMakeLists.txt
@@ -28,7 +28,6 @@ log.test.c
 umlaut.test.c
 unicode.test.c
 variant.test.c
-# xml.test.c
 )
 
 SET(_FILES
@@ -59,7 +58,6 @@ translation.c
 umlaut.c
 unicode.c
 variant.c
-xml.c
 )
 
 FOREACH(_FILE ${_FILES})
diff --git a/src/util/xml.c b/src/util/xml.c
deleted file mode 100644
index 7ce893916..000000000
--- a/src/util/xml.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/* 
- +-------------------+  Christian Schlittchen <corwin@amber.kn-bremen.de>
- |                   |  Enno Rehling <enno@eressea.de>
- | Eressea PBEM host |  Katja Zedel <katze@felidae.kn-bremen.de>
- | (c) 1998 - 2003   |  Henning Peters <faroul@beyond.kn-bremen.de>
- |                   |  Ingo Wilken <Ingo.Wilken@informatik.uni-oldenburg.de>
- +-------------------+  Stefan Reich <reich@halbling.de>
-
- This program may not be used, modified or distributed
- without prior permission by the authors of Eressea.
- */
-#include <platform.h>
-#include "xml.h"
-
-/* util includes */
-#include "log.h"
-#include "assert.h"
-
-#include <libxml/catalog.h>
-#include <libxml/xmlstring.h>
-
-/* libc includes */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-int xml_ivalue(xmlNodePtr node, const char *name, int dflt)
-{
-    int i = dflt;
-    xmlChar *propValue = xmlGetProp(node, BAD_CAST name);
-    if (propValue != NULL) {
-        i = atoi((const char *)propValue);
-        xmlFree(propValue);
-    }
-    return i;
-}
-
-bool xml_bvalue(xmlNodePtr node, const char *name, bool dflt)
-{
-    bool result = dflt;
-    xmlChar *propValue = xmlGetProp(node, BAD_CAST name);
-    if (propValue != NULL) {
-        if (strcmp((const char *)propValue, "no") == 0)
-            result = false;
-        else if (strcmp((const char *)propValue, "yes") == 0)
-            result = true;
-        else if (strcmp((const char *)propValue, "false") == 0)
-            result = false;
-        else if (strcmp((const char *)propValue, "true") == 0)
-            result = true;
-        else if (strcmp((const char *)propValue, "1") == 0) {
-            log_warning("bool value is '1': %s::%s\n", node->name, name);
-            result = true;
-        }
-        else if (strcmp((const char *)propValue, "0") == 0) {
-            log_warning("bool value is '0': %s::%s\n", node->name, name);
-            result = false;
-        }
-        xmlFree(propValue);
-    }
-    return result;
-}
-
-double xml_fvalue(xmlNodePtr node, const char *name, double dflt)
-{
-    double result = dflt;
-    xmlChar *propValue = xmlGetProp(node, BAD_CAST name);
-    if (propValue != NULL) {
-        result = atof((const char *)propValue);
-        xmlFree(propValue);
-    }
-    return result;
-}
-
-/* new xml functions */
-/* libxml includes */
-#include <libxml/tree.h>
-#include <libxml/parser.h>
-
-typedef struct xml_reader {
-    struct xml_reader *next;
-    xml_callback callback;
-} xml_reader;
-
-static xml_reader *xmlReaders;
-
-void xml_done(void) {
-    xml_reader ** xrp = &xmlReaders;
-    while (*xrp) {
-        xml_reader *xr = *xrp;
-        *xrp = xr->next;
-        free(xr);
-    }
-}
-
-void xml_register_callback(xml_callback callback)
-{
-    xml_reader *reader = (xml_reader *)malloc(sizeof(xml_reader));
-    xml_reader **insert = &xmlReaders;
-    assert_alloc(reader);
-    reader->callback = callback;
-    reader->next = NULL;
-
-    while (*insert)
-        insert = &(*insert)->next;
-    *insert = reader;
-}
-
-int read_xml(const char *filename)
-{
-    xml_reader *reader = xmlReaders;
-    xmlDocPtr doc;
-    int results = 0;
-
-    doc = xmlReadFile(filename, NULL, XML_PARSE_NONET | XML_PARSE_PEDANTIC | XML_PARSE_COMPACT);
-    if (doc == NULL) {
-        log_error("could not open '%s'\n", filename);
-        return -1;
-    }
-    while (reader != NULL) {
-        int i = reader->callback(doc);
-        if (i < 0) {
-            return i;
-        }
-        results += i;
-        reader = reader->next;
-    }
-    xmlFreeDoc(doc);
-    return (results > 0) ? 0 : -1;
-}
diff --git a/src/util/xml.h b/src/util/xml.h
deleted file mode 100644
index c7a67a82c..000000000
--- a/src/util/xml.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* 
- +-------------------+  Christian Schlittchen <corwin@amber.kn-bremen.de>
- |                   |  Enno Rehling <enno@eressea.de>
- | Eressea PBEM host |  Katja Zedel <katze@felidae.kn-bremen.de>
- | (c) 1998 - 2003   |  Henning Peters <faroul@beyond.kn-bremen.de>
- |                   |  Ingo Wilken <Ingo.Wilken@informatik.uni-oldenburg.de>
- +-------------------+  Stefan Reich <reich@halbling.de>
-
- This program may not be used, modified or distributed 
- without prior permission by the authors of Eressea.
-*/
-
-#ifndef H_UTIL_XML
-#define H_UTIL_XML
-
-#include <stdbool.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-  /* new xml functions: */
-#include <libxml/tree.h>
-
-
-    typedef int (*xml_callback) (xmlDocPtr);
-
-    void xml_register_callback(xml_callback callback);
-    double xml_fvalue(xmlNodePtr node, const char *name, double dflt);
-    int xml_ivalue(xmlNodePtr node, const char *name, int dflt);
-    bool xml_bvalue(xmlNodePtr node, const char *name, bool dflt);
-
-    void xml_done(void);
-    int read_xml(const char *filename);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/src/xmlreader.c b/src/xmlreader.c
deleted file mode 100644
index 2decd9cb5..000000000
--- a/src/xmlreader.c
+++ /dev/null
@@ -1,1361 +0,0 @@
-/* 
-+-------------------+
-|                   |  Enno Rehling <enno@eressea.de>
-| Eressea PBEM host |  Christian Schlittchen <corwin@amber.kn-bremen.de>
-| (c) 1998 - 2004   |  Katja Zedel <katze@felidae.kn-bremen.de>
-|                   |  Henning Peters <faroul@beyond.kn-bremen.de>
-+-------------------+
-
-This program may not be used, modified or distributed
-without prior permission by the authors of Eressea.
-*/
-
-#ifdef _MSC_VER
-#include <platform.h>
-#endif
-
-#include "xmlreader.h"
-
-#include "alchemy.h"
-#include "guard.h"
-#include "keyword.h"
-#include "move.h"
-#include "prefix.h"
-
-#include "attributes/attributes.h"
-#include "modules/score.h"
-
-#include "kernel/building.h"
-#include "kernel/calendar.h"
-#include "kernel/item.h"
-#include "kernel/messages.h"
-#include "kernel/race.h"
-#include "kernel/region.h"
-#include "kernel/resources.h"
-#include "kernel/ship.h"
-#include "kernel/terrain.h"
-#include "kernel/skills.h"
-#include "kernel/spell.h"
-#include "kernel/spellbook.h"
-
-#include "util/attrib.h"
-#include "util/crmessage.h"
-#include "util/functions.h"
-#include "util/language.h"
-#include "util/log.h"
-#include "util/message.h"
-#include "util/nrmessage.h"
-#include "util/strings.h"
-#include "util/xml.h"
-
-/* libxml includes */
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
-#include <libxml/encoding.h>
-
-/* libc includes */
-#include <assert.h>
-#include <ctype.h>
-#include <limits.h>
-#include <string.h>
-
-
-static void mask_races(xmlNodePtr node, const char *key, int *maskp) {
-    xmlChar *propValue = xmlGetProp(node, BAD_CAST key);
-    int mask = 0;
-    assert(maskp);
-    if (propValue) {
-        mask = rc_get_mask((char *)propValue);
-        xmlFree(propValue);
-    }
-    *maskp = mask;
-}
-
-static variant xml_fraction(xmlNodePtr node, const char *name) {
-    xmlChar *propValue = xmlGetProp(node, BAD_CAST name);
-    if (propValue != NULL) {
-        int num, den = 100;
-        double fval = atof((const char *)propValue);
-        num = (int)(fval * den + 0.5);
-        xmlFree(propValue);
-        return frac_make(num, den);
-    }
-    return frac_make(0, 1);
-}
-
-static spellref *xml_spellref(xmlNode * node, const char *name)
-{
-    xmlChar *propValue = xmlGetProp(node, BAD_CAST name);
-    if (propValue != NULL) {
-        spellref *ref = spellref_create(NULL, (const char *)propValue);
-        xmlFree(propValue);
-        return ref;
-    }
-    return NULL;
-}
-
-static resource_mod * xml_readmodifiers(xmlXPathObjectPtr result, xmlNodePtr node) {
-    /* reading eressea/resources/resource/modifier */
-    if (result->nodesetval != NULL && result->nodesetval->nodeNr > 0) {
-        int k;
-        resource_mod * modifiers =
-            calloc(result->nodesetval->nodeNr + 1, sizeof(resource_mod));
-        for (k = 0; k != result->nodesetval->nodeNr; ++k) {
-            xmlNodePtr node = result->nodesetval->nodeTab[k];
-            xmlChar *propValue;
-            building_type *btype = NULL;
-
-            mask_races(node, "races", &modifiers[k].race_mask);
-
-            propValue = xmlGetProp(node, BAD_CAST "building");
-            if (propValue != NULL) {
-                btype = bt_get_or_create((const char *)propValue);
-                xmlFree(propValue);
-            }
-            modifiers[k].btype = btype;
-
-            propValue = xmlGetProp(node, BAD_CAST "type");
-            assert(propValue != NULL);
-            if (strcmp((const char *)propValue, "skill") == 0) {
-                xmlChar *propSkill;
-                skill_t sk = NOSKILL;
-
-                modifiers[k].type = RMT_PROD_SKILL;
-                propSkill = xmlGetProp(node, BAD_CAST "skill");
-                if (propSkill) {
-                    sk = findskill((const char *)propSkill);
-                    xmlFree(propSkill);
-                }
-                modifiers[k].value.sa[0] = (short)sk;
-                modifiers[k].value.sa[1] = (short)xml_ivalue(node, "value", 0);
-            }
-            else if (strcmp((const char *)propValue, "material") == 0) {
-                modifiers[k].value = xml_fraction(node, "value");
-                modifiers[k].type = RMT_PROD_SAVE;
-            }
-            else {
-                if (strcmp((const char *)propValue, "require") == 0) {
-                    modifiers[k].type = RMT_PROD_REQUIRE;
-                }
-                else if (strcmp((const char *)propValue, "save") == 0) {
-                    modifiers[k].type = RMT_USE_SAVE;
-                    modifiers[k].value = xml_fraction(node, "value");
-                }
-                else {
-                    log_error("unknown type '%s' for resourcelimit-modifier", (const char *)propValue);
-                }
-            }
-            xmlFree(propValue);
-        }
-        return modifiers;
-    }
-    return NULL;
-}
-
-static void
-xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray)
-{
-    int req;
-    requirement *radd = *reqArray;
-
-    assert(radd == NULL);
-    if (nodeNr == 0)
-        return;
-
-    radd = *reqArray = calloc(sizeof(requirement), nodeNr + 1);
-
-    for (req = 0; req != nodeNr; ++req) {
-        xmlNodePtr node = nodeTab[req];
-        xmlChar *propValue;
-
-        radd->number = xml_ivalue(node, "quantity", 1);
-
-        propValue = xmlGetProp(node, BAD_CAST "type");
-        radd->rtype = rt_get_or_create((const char *)propValue);
-        xmlFree(propValue);
-
-        ++radd;
-    }
-}
-
-static construction *
-xml_readconstruction(xmlXPathContextPtr xpath, xmlNodePtr node)
-{
-    construction *con;
-    xmlChar *propValue;
-    xmlXPathObjectPtr req;
-    skill_t sk = NOSKILL;
-
-    propValue = xmlGetProp(node, BAD_CAST "skill");
-    if (propValue != NULL) {
-        sk = findskill((const char *)propValue);
-        if (sk == NOSKILL) {
-            log_error("construction requires skill '%s' that does not exist.\n", (const char *)propValue);
-            xmlFree(propValue);
-            return NULL;
-        }
-        xmlFree(propValue);
-    }
-
-    con = (construction *)calloc(sizeof(construction), 1);
-
-    con->skill = sk;
-    con->maxsize = xml_ivalue(node, "maxsize", -1);
-    con->minskill = xml_ivalue(node, "minskill", -1);
-    con->reqsize = xml_ivalue(node, "reqsize", 1);
-
-    /* read construction/requirement */
-    xpath->node = node;
-    req = xmlXPathEvalExpression(BAD_CAST "requirement", xpath);
-    xml_readrequirements(req->nodesetval->nodeTab,
-        req->nodesetval->nodeNr, &con->materials);
-    xmlXPathFreeObject(req);
-
-    return con;
-}
-
-static void
-xml_readconstructions(xmlXPathContextPtr xpath, xmlNodeSetPtr nodeSet, building_type *btype)
-{
-    building_stage **stage_ptr = &btype->stages;
-    int k;
-
-    for (k = 0; k != nodeSet->nodeNr; ++k) {
-        building_stage *stage = calloc(1, sizeof(building_stage));
-        xmlNodePtr node = nodeSet->nodeTab[k];
-        construction *con = xml_readconstruction(xpath, node);
-        xmlChar *propValue = xmlGetProp(node, BAD_CAST "name");
-
-        if (propValue != NULL) {
-            stage->name = str_strdup((const char *)propValue);
-            xmlFree(propValue);
-        }
-        stage->next = NULL;
-        stage->construction = con;
-
-        *stage_ptr = stage;
-        stage_ptr = &stage->next;
-    }
-}
-
-static int
-parse_function(xmlNodePtr node, pf_generic * funPtr, xmlChar ** namePtr)
-{
-    pf_generic fun;
-    xmlChar *propValue = xmlGetProp(node, BAD_CAST "value");
-    assert(propValue != NULL);
-    fun = get_function((const char *)propValue);
-    xmlFree(propValue);
-    propValue = xmlGetProp(node, BAD_CAST "name");
-    *namePtr = propValue;
-    *funPtr = fun;
-    return 0;
-}
-
-static int parse_buildings(xmlDocPtr doc)
-{
-    xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
-    xmlXPathObjectPtr buildings;
-    int result = 0;
-
-    /* reading eressea/buildings/building */
-    buildings =
-        xmlXPathEvalExpression(BAD_CAST "/eressea/buildings/building", xpath);
-    if (buildings->nodesetval != NULL) {
-        xmlNodeSetPtr nodes = buildings->nodesetval;
-        int i;
-        result += nodes->nodeNr;
-        for (i = 0; i != nodes->nodeNr; ++i) {
-            xmlNodePtr node = nodes->nodeTab[i];
-            xmlChar *propValue;
-            building_type *btype;
-            xmlXPathObjectPtr result;
-            int k;
-
-            propValue = xmlGetProp(node, BAD_CAST "name");
-            assert(propValue != NULL);
-            btype = bt_get_or_create((const char *)propValue);
-            xmlFree(propValue);
-
-            btype->capacity = xml_ivalue(node, "capacity", btype->capacity);
-            btype->maxcapacity = xml_ivalue(node, "maxcapacity", btype->maxcapacity);
-            btype->maxsize = xml_ivalue(node, "maxsize", btype->maxsize);
-
-            btype->magres = frac_make(xml_ivalue(node, "magres", 0), 100);
-            btype->magresbonus = xml_ivalue(node, "magresbonus", btype->magresbonus);
-            btype->fumblebonus = xml_ivalue(node, "fumblebonus", btype->fumblebonus);
-            btype->auraregen = xml_fvalue(node, "auraregen", btype->auraregen);
-            btype->taxes = xml_ivalue(node, "taxes", btype->taxes);
-
-            if (xml_bvalue(node, "nodestroy", false))
-                btype->flags |= BTF_INDESTRUCTIBLE;
-            if (xml_bvalue(node, "nobuild", false))
-                btype->flags |= BTF_NOBUILD;
-            if (xml_bvalue(node, "unique", false))
-                btype->flags |= BTF_UNIQUE;
-            if (xml_bvalue(node, "decay", false))
-                btype->flags |= BTF_DECAY;
-            if (xml_bvalue(node, "magic", false))
-                btype->flags |= BTF_MAGIC;
-            if (xml_bvalue(node, "namechange", true))
-                btype->flags |= BTF_NAMECHANGE;
-            if (xml_bvalue(node, "fort", false))
-                btype->flags |= BTF_FORTIFICATION;
-            if (xml_bvalue(node, "oneperturn", false))
-                btype->flags |= BTF_ONEPERTURN;
-
-            /* reading eressea/buildings/building/modifier */
-            xpath->node = node;
-            result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
-            btype->modifiers = xml_readmodifiers(result, node);
-            xmlXPathFreeObject(result);
-
-            /* reading eressea/buildings/building/construction */
-            xpath->node = node;
-            result = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
-            xml_readconstructions(xpath, result->nodesetval, btype);
-            xmlXPathFreeObject(result);
-
-            /* reading eressea/buildings/building/function */
-            xpath->node = node;
-            result = xmlXPathEvalExpression(BAD_CAST "function", xpath);
-            for (k = 0; k != result->nodesetval->nodeNr; ++k) {
-                xmlNodePtr node = result->nodesetval->nodeTab[k];
-                pf_generic fun;
-                parse_function(node, &fun, &propValue);
-
-                if (fun == NULL) {
-                    log_error("unknown function name '%s' for building %s\n", (const char *)propValue, btype->_name);
-                    xmlFree(propValue);
-                    continue;
-                }
-                assert(propValue != NULL);
-                log_error("unknown function type '%s' for building %s\n", (const char *)propValue, btype->_name);
-                xmlFree(propValue);
-            }
-            xmlXPathFreeObject(result);
-
-            /* reading eressea/buildings/building/maintenance */
-            result = xmlXPathEvalExpression(BAD_CAST "maintenance", xpath);
-            for (k = 0; k != result->nodesetval->nodeNr; ++k) {
-                xmlNodePtr node = result->nodesetval->nodeTab[k];
-                maintenance *mt;
-
-                if (btype->maintenance == NULL) {
-                    btype->maintenance = (struct maintenance *)
-                        calloc(sizeof(struct maintenance), result->nodesetval->nodeNr + 1);
-                }
-                mt = btype->maintenance + k;
-                mt->number = xml_ivalue(node, "amount", 0);
-
-                propValue = xmlGetProp(node, BAD_CAST "type");
-                assert(propValue != NULL);
-                mt->rtype = rt_get_or_create((const char *)propValue);
-                assert(mt->rtype != NULL);
-                xmlFree(propValue);
-
-                if (xml_bvalue(node, "variable", false))
-                    mt->flags |= MTF_VARIABLE;
-            }
-            xmlXPathFreeObject(result);
-        }
-    }
-    xmlXPathFreeObject(buildings);
-
-    xmlXPathFreeContext(xpath);
-    return result;
-}
-
-static int parse_ships(xmlDocPtr doc)
-{
-    xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
-    xmlXPathObjectPtr ships;
-    int result = 0;
-
-    /* reading eressea/ships/ship */
-    ships = xmlXPathEvalExpression(BAD_CAST "/eressea/ships/ship", xpath);
-    if (ships->nodesetval != NULL) {
-        xmlNodeSetPtr nodes = ships->nodesetval;
-        int i;
-        result += nodes->nodeNr;
-        for (i = 0; i != nodes->nodeNr; ++i) {
-            xmlNodePtr child, node = nodes->nodeTab[i];
-            xmlChar *propValue;
-            ship_type *st;
-            xmlXPathObjectPtr result;
-            int k, c;
-
-            propValue = xmlGetProp(node, BAD_CAST "name");
-            assert(propValue != NULL);
-            st = st_get_or_create((const char *)propValue);
-            xmlFree(propValue);
-
-            st->cabins = xml_ivalue(node, "cabins", 0) * PERSON_WEIGHT;
-            st->cargo = xml_ivalue(node, "cargo", st->cargo);
-            st->combat = xml_ivalue(node, "combat", st->combat);
-            st->damage = xml_fvalue(node, "damage", st->damage);
-            if (xml_bvalue(node, "nocoast", false))
-                st->flags |= SFL_NOCOAST;
-            if (xml_bvalue(node, "fly", false))
-                st->flags |= SFL_FLY;
-            if (xml_bvalue(node, "opensea", false))
-                st->flags |= SFL_OPENSEA;
-            if (xml_bvalue(node, "speedy", false))
-                st->flags |= SFL_SPEEDY;
-            st->fishing = xml_ivalue(node, "fishing", st->fishing);
-            st->cptskill = xml_ivalue(node, "cptskill", st->cptskill);
-            st->minskill = xml_ivalue(node, "minskill", st->minskill);
-            st->sumskill = xml_ivalue(node, "sumskill", st->sumskill);
-            st->range = xml_ivalue(node, "range", st->range);
-            st->range_max = xml_ivalue(node, "maxrange", st->range_max);
-            st->storm = xml_fvalue(node, "storm", st->storm);
-
-            for (child = node->children; child; child = child->next) {
-                if (strcmp((const char *)child->name, "modifier") == 0) {
-                    propValue = xmlGetProp(child, BAD_CAST "type");
-                    if (strcmp((const char *)propValue, "tactics") == 0) {
-                        st->tac_bonus = xml_fvalue(child, "factor", 1.0);
-                    }
-                    else {
-                        int value = xml_ivalue(child, "value", 0);
-                        if (strcmp((const char *)propValue, "attack") == 0) {
-                            st->at_bonus = (int)value;
-                        }
-                        else if (strcmp((const char *)propValue, "defense") == 0) {
-                            st->df_bonus = (int)value;
-                        }
-                    }
-                    xmlFree(propValue);
-                }
-                else if (strcmp((const char *)child->name, "construction") == 0) {
-                    assert(!st->construction);
-                    st->construction = xml_readconstruction(xpath, child);
-                }
-            }
-            /* reading eressea/ships/ship/coast */
-            xpath->node = node;
-            result = xmlXPathEvalExpression(BAD_CAST "coast", xpath);
-            for (c = 0, k = 0; k != result->nodesetval->nodeNr; ++k) {
-                xmlNodePtr node = result->nodesetval->nodeTab[k];
-
-                if (k == 0) {
-                    assert(st->coasts == NULL);
-                    st->coasts =
-                        (terrain_type **)malloc(sizeof(terrain_type *) *
-                        (result->nodesetval->nodeNr + 1));
-                    st->coasts[result->nodesetval->nodeNr] = NULL;
-                }
-
-                propValue = xmlGetProp(node, BAD_CAST "terrain");
-                assert(propValue != NULL);
-                st->coasts[c] = get_or_create_terrain((const char *)propValue);
-                if (st->coasts[c] != NULL)
-                    ++c;
-                else {
-                    log_warning("ship %s mentions a non-existing terrain %s.\n", st->_name, propValue);
-                }
-                xmlFree(propValue);
-            }
-            xmlXPathFreeObject(result);
-        }
-    }
-    xmlXPathFreeObject(ships);
-
-    xmlXPathFreeContext(xpath);
-    return result;
-}
-
-static void xml_readpotion(xmlNodePtr node, item_type * itype)
-{
-    int level = xml_ivalue(node, "level", 0);
-
-    if ((itype->flags & ITF_CANUSE) == 0) {
-        log_error("potion %s has no use attribute", itype->rtype->_name);
-        itype->flags |= ITF_CANUSE;
-    }
-    new_potiontype(itype, level);
-}
-
-static luxury_type *xml_readluxury(xmlNodePtr node, item_type * itype)
-{
-    int price = xml_ivalue(node, "price", 0);
-    if (itype->rtype->ltype) {
-        itype->rtype->ltype->price = price;
-        return itype->rtype->ltype;
-    }
-    return new_luxurytype(itype, price);
-}
-
-static armor_type *xml_readarmor(xmlNodePtr node, item_type * itype)
-{
-    armor_type *atype = NULL;
-    unsigned int flags = ATF_NONE;
-    int ac = xml_ivalue(node, "ac", 0);
-    double penalty = xml_fvalue(node, "penalty", 0.0);
-    variant magres = xml_fraction(node, "magres");
-
-    if (xml_bvalue(node, "laen", false))
-        flags |= ATF_LAEN;
-    if (xml_bvalue(node, "shield", false))
-        flags |= ATF_SHIELD;
-
-    atype = new_armortype(itype, penalty, magres, ac, flags);
-    atype->projectile = (float)xml_fvalue(node, "projectile", 0.0);
-    return atype;
-}
-
-static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype)
-{
-    xmlNodePtr node = xpath->node;
-    weapon_type *wtype = NULL;
-    unsigned int flags = WTF_NONE;
-    xmlXPathObjectPtr result;
-    xmlChar *propValue;
-    int k;
-    skill_t sk;
-    int offmod = xml_ivalue(node, "offmod", 0);
-    int defmod = xml_ivalue(node, "defmod", 0);
-    int reload = xml_ivalue(node, "reload", 0);
-    variant magres = xml_fraction(node, "magres");
-
-    if (xml_bvalue(node, "armorpiercing", false))
-        flags |= WTF_ARMORPIERCING;
-    if (xml_bvalue(node, "magical", false))
-        flags |= WTF_MAGICAL;
-    if (xml_bvalue(node, "missile", false))
-        flags |= WTF_MISSILE;
-    if (xml_bvalue(node, "pierce", false))
-        flags |= WTF_PIERCE;
-    if (xml_bvalue(node, "cut", false))
-        flags |= WTF_CUT;
-    if (xml_bvalue(node, "bash", false))
-        flags |= WTF_BLUNT;
-    if (xml_bvalue(node, "siege", false))
-        flags |= WTF_SIEGE;
-    if (xml_bvalue(node, "horse", (flags & WTF_MISSILE) == 0))
-        flags |= WTF_HORSEBONUS;
-    if (xml_bvalue(node, "useshield", true))
-        flags |= WTF_USESHIELD;
-
-    propValue = xmlGetProp(node, BAD_CAST "skill");
-    assert(propValue != NULL);
-    sk = findskill((const char *)propValue);
-    assert(sk != NOSKILL);
-    xmlFree(propValue);
-
-    wtype = new_weapontype(itype, flags, magres, NULL, offmod, defmod, reload, sk);
-
-    /* reading weapon/damage */
-    xpath->node = node;
-    result = xmlXPathEvalExpression(BAD_CAST "damage", xpath);
-    assert(result->nodesetval->nodeNr <= 2);
-    for (k = 0; k != result->nodesetval->nodeNr; ++k) {
-        xmlNodePtr node = result->nodesetval->nodeTab[k];
-        int pos = 0;
-
-        propValue = xmlGetProp(node, BAD_CAST "type");
-        if (strcmp((const char *)propValue, "footman") != 0) {
-            pos = 1;
-        }
-        xmlFree(propValue);
-
-        propValue = xmlGetProp(node, BAD_CAST "value");
-        wtype->damage[pos] = str_strdup((const char *)propValue); /* TODO: this is a memory leak */
-        xmlFree(propValue);
-    }
-    xmlXPathFreeObject(result);
-
-    /* reading weapon/modifier */
-    xpath->node = node;
-    result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
-    assert(wtype->modifiers == NULL);
-    wtype->modifiers = calloc(result->nodesetval->nodeNr + 1, sizeof(weapon_mod));
-    for (k = 0; k != result->nodesetval->nodeNr; ++k) {
-        xmlNodePtr node = result->nodesetval->nodeTab[k];
-        int flags = 0;
-
-        if (xml_bvalue(node, "walking", false))
-            flags |= WMF_WALKING;
-        if (xml_bvalue(node, "riding", false))
-            flags |= WMF_RIDING;
-        if (xml_bvalue(node, "against_walking", false))
-            flags |= WMF_AGAINST_WALKING;
-        if (xml_bvalue(node, "against_riding", false))
-            flags |= WMF_AGAINST_RIDING;
-        if (xml_bvalue(node, "offensive", false))
-            flags |= WMF_OFFENSIVE;
-        if (xml_bvalue(node, "defensive", false))
-            flags |= WMF_DEFENSIVE;
-
-        propValue = xmlGetProp(node, BAD_CAST "type");
-        if (strcmp((const char *)propValue, "damage") == 0)
-            flags |= WMF_DAMAGE;
-        else if (strcmp((const char *)propValue, "skill") == 0)
-            flags |= WMF_SKILL;
-        else if (strcmp((const char *)propValue, "missile_target") == 0)
-            flags |= WMF_MISSILE_TARGET;
-        xmlFree(propValue);
-
-        wtype->modifiers[k].flags = flags;
-        wtype->modifiers[k].value = xml_ivalue(node, "value", 0);
-
-        mask_races(node, "races", &wtype->modifiers[k].race_mask);
-        wtype->modifiers[k].race_mask = 0;
-    }
-    xmlXPathFreeObject(result);
-
-    /* reading weapon/function */
-    xpath->node = node;
-    result = xmlXPathEvalExpression(BAD_CAST "function", xpath);
-    for (k = 0; k != result->nodesetval->nodeNr; ++k) {
-        xmlNodePtr node = result->nodesetval->nodeTab[k];
-        xmlChar *propValue;
-        pf_generic fun;
-
-        parse_function(node, &fun, &propValue);
-        if (fun == NULL) {
-            log_error("unknown function name '%s' for item '%s'\n", (const char *)propValue, itype->rtype->_name);
-            xmlFree(propValue);
-            continue;
-        }
-        assert(propValue != NULL);
-        if (strcmp((const char *)propValue, "attack") == 0) {
-            wtype->attack = (wtype_attack)fun;
-        }
-        else {
-            log_error("unknown function type '%s' for item '%s'\n", (const char *)propValue, itype->rtype->_name);
-        }
-        xmlFree(propValue);
-    }
-    xmlXPathFreeObject(result);
-
-    xpath->node = node;
-    return wtype;
-}
-
-static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
-{
-    xmlNodePtr child, node = xpath->node;
-    item_type *itype = NULL;
-    unsigned int flags = ITF_NONE;
-
-    if (xml_bvalue(node, "cursed", false))
-        flags |= ITF_CURSED;
-    if (xml_bvalue(node, "use", false))
-        flags |= ITF_CANUSE;
-    if (xml_bvalue(node, "notlost", false))
-        flags |= ITF_NOTLOST;
-    if (xml_bvalue(node, "herb", false))
-        flags |= ITF_HERB;
-    if (xml_bvalue(node, "big", false))
-        flags |= ITF_BIG;
-    if (xml_bvalue(node, "animal", false))
-        flags |= ITF_ANIMAL;
-    if (xml_bvalue(node, "vehicle", false))
-        flags |= ITF_VEHICLE;
-
-    itype = rtype->itype ? rtype->itype : it_get_or_create(rtype);
-    /* exparse: recreate child data. */
-    if (itype->construction) {
-        free_construction(itype->construction);
-        itype->construction = NULL;
-    }
-
-    itype->weight = xml_ivalue(node, "weight", 0);
-    itype->capacity = xml_ivalue(node, "capacity", 0);
-    itype->score = xml_ivalue(node, "score", 0);
-
-    mask_races(node, "allow", &itype->mask_allow);
-    mask_races(node, "deny", &itype->mask_deny);
-    itype->flags |= flags;
-
-    for (child = node->children; child; child = child->next) {
-        if (strcmp((const char *)child->name, "construction") == 0) {
-            /* reading item/construction */
-            assert(!itype->construction);
-            xpath->node = child;
-            itype->construction = xml_readconstruction(xpath, child);
-        }
-        else if (strcmp((const char *)child->name, "weapon") == 0) {
-            /* reading item/weapon */
-            assert(!rtype->wtype);
-            xpath->node = child;
-            rtype->wtype = xml_readweapon(xpath, itype);
-        }
-        else if (strcmp((const char *)child->name, "armor") == 0) {
-            /* reading item/weapon */
-            assert(!rtype->atype);
-            rtype->atype = xml_readarmor(child, itype);
-        }
-        else if (strcmp((const char *)child->name, "luxury") == 0) {
-            /* reading item/luxury */
-            assert(!rtype->ltype);
-            rtype->ltype = xml_readluxury(child, itype);
-        }
-        else if (strcmp((const char *)child->name, "potion") == 0) {
-            /* reading item/potion */
-            xml_readpotion(child, itype);
-        }
-    }
-
-    if (!itype->score) {
-        /* do this last, because score depends on itype data */
-        itype->score = default_score(itype);
-    }
-    return itype;
-}
-
-static int parse_resources(xmlDocPtr doc)
-{
-    xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
-    xmlXPathObjectPtr resources;
-    int results = 0;
-
-    /* reading eressea/resources/resource */
-    resources =
-        xmlXPathEvalExpression(BAD_CAST "/eressea/resources/resource", xpath);
-    if (resources->nodesetval) {
-        int i;
-        xmlNodeSetPtr nodes = resources->nodesetval;
-        results = nodes->nodeNr;
-        for (i = 0; i != nodes->nodeNr; ++i) {
-            xmlNodePtr node = nodes->nodeTab[i];
-            xmlChar *propValue, *name, *appearance;
-            resource_type *rtype;
-            unsigned int flags = RTF_NONE;
-            xmlXPathObjectPtr result;
-
-            if (xml_bvalue(node, "pooled", true))
-                flags |= RTF_POOLED;
-
-            name = xmlGetProp(node, BAD_CAST "name");
-            if (!name) {
-                assert(name);
-                log_error("invalid resource %d has no name", i);
-                continue;
-            }
-
-            rtype = rt_get_or_create((const char *)name);
-            /* exparse: recreate child data. */
-            if (rtype->atype) {
-                free_atype(rtype->atype);
-                rtype->atype = NULL;
-            }
-            if (rtype->wtype) {
-                free_wtype(rtype->wtype);
-                rtype->wtype = NULL;
-            }
-
-            rtype->flags |= flags;
-            xmlFree(name);
-
-            /* reading eressea/resources/resource/function */
-            xpath->node = node;
-            result = xmlXPathEvalExpression(BAD_CAST "function", xpath);
-            if (result->nodesetval != NULL) {
-                int k;
-                for (k = 0; k != result->nodesetval->nodeNr; ++k) {
-                    xmlNodePtr node = result->nodesetval->nodeTab[k];
-                    pf_generic fun;
-
-                    parse_function(node, &fun, &propValue);
-                    if (fun == NULL) {
-                        log_error("unknown function name '%s' for resource %s\n", (const char *)propValue, rtype->_name);
-                        xmlFree(propValue);
-                        continue;
-                    }
-
-                    assert(propValue != NULL);
-                    if (strcmp((const char *)propValue, "change") == 0) {
-                        rtype->uchange = (rtype_uchange)fun;
-                    }
-                    else if (strcmp((const char *)propValue, "name") == 0) {
-                        rtype->name = (rtype_name)fun;
-                    }
-                    else {
-                        log_error("unknown function type '%s' for resource %s\n", (const char *)propValue, rtype->_name);
-                    }
-                    xmlFree(propValue);
-                }
-            }
-            xmlXPathFreeObject(result);
-
-            if (xml_bvalue(node, "limited", false)) {
-                rtype->flags |= RTF_LIMITED;
-            }
-            xpath->node = node;
-            result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
-            rtype->modifiers = xml_readmodifiers(result, node);
-            xmlXPathFreeObject(result);
-
-            /* reading eressea/resources/resource/item */
-            xpath->node = node;
-            result = xmlXPathEvalExpression(BAD_CAST "item", xpath);
-            assert(result->nodesetval->nodeNr <= 1);
-            if (result->nodesetval->nodeNr != 0) {
-                rtype->flags |= RTF_ITEM;
-                xpath->node = result->nodesetval->nodeTab[0];
-                rtype->itype = xml_readitem(xpath, rtype);
-                appearance = xmlGetProp(node, BAD_CAST "appearance");
-                if (appearance) {
-                    it_set_appearance(rtype->itype, (const char *)appearance);
-                    xmlFree(appearance);
-                }
-            }
-            xmlXPathFreeObject(result);
-
-            if (xml_bvalue(node, "material", false)) {
-                assert(!rtype->itype || rtype->itype->construction);
-                rmt_create(rtype);
-            }
-        }
-    }
-    xmlXPathFreeObject(resources);
-
-    xmlXPathFreeContext(xpath);
-
-    /* make sure old items (used in requirements) are available */
-    init_resources();
-
-    return results;
-}
-
-static int parse_spellbooks(xmlDocPtr doc)
-{
-    xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
-    xmlXPathObjectPtr spellbooks;
-    int results = 0;
-
-    /* reading eressea/spells/spell */
-    spellbooks = xmlXPathEvalExpression(BAD_CAST "/eressea/spellbook", xpath);
-
-    if (spellbooks->nodesetval != NULL) {
-        xmlNodeSetPtr nodes = spellbooks->nodesetval;
-        int i, k;
-
-        results += nodes->nodeNr;
-        for (i = 0; i != nodes->nodeNr; ++i) {
-            xmlXPathObjectPtr result;
-            xmlNodePtr node = nodes->nodeTab[i];
-            xmlChar *propValue;
-            spellbook * sb;
-
-            propValue = xmlGetProp(node, BAD_CAST "name");
-            if (propValue) {
-                sb = get_spellbook((const char *)propValue);
-                xmlFree(propValue);
-            }
-            else {
-                log_error("spellbook at index '%d' has n name\n", i);
-                continue;
-            }
-
-            xpath->node = node;
-            result = xmlXPathEvalExpression(BAD_CAST "entry", xpath);
-
-            if (result->nodesetval->nodeNr > 0) {
-                for (k = 0; k != result->nodesetval->nodeNr; ++k) {
-                    xmlNodePtr node = result->nodesetval->nodeTab[k];
-                    int level = xml_ivalue(node, "level", -1);
-
-                    if (level > 0 && (propValue = xmlGetProp(node, BAD_CAST "spell")) != NULL) {
-                        spellbook_addref(sb, (const char *)propValue, level);
-                        xmlFree(propValue);
-                    }
-                    else {
-                        log_error("invalid entry at index '%d' in spellbook '%s'\n", k, sb->name);
-                    }
-                }
-            }
-            xmlXPathFreeObject(result);
-        }
-    }
-    xmlXPathFreeObject(spellbooks);
-    xmlXPathFreeContext(xpath);
-    return results;
-}
-
-static int parse_spells(xmlDocPtr doc)
-{
-    xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
-    xmlXPathObjectPtr spells;
-    int result = 0;
-
-    /* reading eressea/spells/spell */
-    spells = xmlXPathEvalExpression(BAD_CAST "/eressea/spells/spell", xpath);
-    if (spells->nodesetval != NULL) {
-        xmlNodeSetPtr nodes = spells->nodesetval;
-        int i;
-
-        result += nodes->nodeNr;
-        for (i = 0; i != nodes->nodeNr; ++i) {
-            xmlXPathObjectPtr result;
-            xmlNodePtr node = nodes->nodeTab[i];
-            xmlChar *propValue;
-            int k;
-            spell_component *component;
-            spell *sp;
-            static int modes[] = { 0, PRECOMBATSPELL, COMBATSPELL, POSTCOMBATSPELL };
-
-            /* spellname */
-            propValue = xmlGetProp(node, BAD_CAST "name");
-            assert(propValue != NULL);
-            sp = create_spell((const char *)propValue);
-            xmlFree(propValue);
-            if (!sp) {
-                continue;
-            }
-
-            propValue = xmlGetProp(node, BAD_CAST "parameters");
-            if (propValue) {
-                sp->parameter = str_strdup((const char *)propValue);
-                xmlFree(propValue);
-            }
-
-            propValue = xmlGetProp(node, BAD_CAST "syntax");
-            if (propValue) {
-                sp->syntax = str_strdup((const char *)propValue);
-                xmlFree(propValue);
-            }
-            sp->rank = (char)xml_ivalue(node, "rank", sp->rank);
-            if (xml_bvalue(node, "los", false))
-                sp->sptyp |= TESTCANSEE;        /* must see or have contact */
-            if (xml_bvalue(node, "ship", false))
-                sp->sptyp |= ONSHIPCAST;
-            if (xml_bvalue(node, "ocean", false))
-                sp->sptyp |= OCEANCASTABLE;
-            if (xml_bvalue(node, "far", false))
-                sp->sptyp |= FARCASTING;
-            if (xml_bvalue(node, "variable", false))
-                sp->sptyp |= SPELLLEVEL;
-
-            if (xml_bvalue(node, "globaltarget", false))
-                sp->sptyp |= GLOBALTARGET;       /* target need not be in same region */
-            if (xml_bvalue(node, "buildingtarget", false))
-                sp->sptyp |= BUILDINGSPELL;
-            if (xml_bvalue(node, "shiptarget", false))
-                sp->sptyp |= SHIPSPELL;
-            if (xml_bvalue(node, "unittarget", false))
-                sp->sptyp |= UNITSPELL;
-            if (xml_bvalue(node, "regiontarget", false))
-                sp->sptyp |= REGIONSPELL;
-
-            k = xml_ivalue(node, "combat", 0);
-            if (k >= 0 && k <= 3) {
-                sp->sptyp |= modes[k];
-            }
-            /* reading eressea/spells/spell/resource */
-            xpath->node = node;
-            result = xmlXPathEvalExpression(BAD_CAST "resource", xpath);
-            if (result->nodesetval->nodeNr) {
-                sp->components =
-                    (spell_component *)malloc(sizeof(spell_component) *
-                    (result->nodesetval->nodeNr + 1));
-                sp->components[result->nodesetval->nodeNr].type = 0;
-            }
-            for (component = sp->components, k = 0; k != result->nodesetval->nodeNr;
-                ++k) {
-                const resource_type *rtype;
-                xmlNodePtr node = result->nodesetval->nodeTab[k];
-                propValue = xmlGetProp(node, BAD_CAST "name");
-                assert(propValue);
-                rtype = rt_get_or_create((const char *)propValue);
-                component->type = rtype;
-                xmlFree(propValue);
-                component->amount = xml_ivalue(node, "amount", 1);
-                component->cost = SPC_FIX;
-                propValue = xmlGetProp(node, BAD_CAST "cost");
-                if (propValue != NULL) {
-                    if (strcmp((const char *)propValue, "linear") == 0) {
-                        if ((sp->sptyp&SPELLLEVEL) == 0) {
-                            log_error("spell '%s' has linear cost but fixed level\n", sp->sname);
-                        }
-                        component->cost = SPC_LINEAR;
-                    }
-                    else if (strcmp((const char *)propValue, "level") == 0) {
-                        if ((sp->sptyp&SPELLLEVEL) == 0) {
-                            log_error("spell '%s' has levelled cost but fixed level\n", sp->sname);
-                        }
-                        component->cost = SPC_LEVEL;
-                    }
-                    xmlFree(propValue);
-                }
-                component++;
-            }
-            xmlXPathFreeObject(result);
-        }
-    }
-
-    xmlXPathFreeObject(spells);
-
-    xmlXPathFreeContext(xpath);
-
-    return result;
-}
-
-static void parse_ai(race * rc, xmlNodePtr node)
-{
-    xmlChar *propValue;
-    
-    propValue = xmlGetProp(node, BAD_CAST "scare");
-    if (propValue) {
-        rc_set_param(rc, "scare", (const char *)propValue);
-        xmlFree(propValue);
-    }
-    rc->splitsize = xml_ivalue(node, "splitsize", 0);
-    if (xml_bvalue(node, "killpeasants", false))
-        rc->flags |= RCF_KILLPEASANTS;
-    if (xml_bvalue(node, "moverandom", false))
-        rc->flags |= RCF_MOVERANDOM;
-    if (xml_bvalue(node, "learn", false))
-        rc->flags |= RCF_LEARN;
-    if (xml_bvalue(node, "moveattack", false))
-        rc->flags |= RCF_ATTACK_MOVED;
-}
-
-static int parse_races(xmlDocPtr doc)
-{
-    xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
-    xmlXPathObjectPtr races;
-    int results = 0;
-
-    /* reading eressea/races/race */
-    races = xmlXPathEvalExpression(BAD_CAST "/eressea/races/race", xpath);
-    if (races->nodesetval) {
-        xmlNodeSetPtr nodes = races->nodesetval;
-        int i;
-        results += nodes->nodeNr;
-        for (i = 0; i != nodes->nodeNr; ++i) {
-            xmlNodePtr node = nodes->nodeTab[i];
-            xmlNodePtr child;
-            xmlChar *propValue;
-            race *rc, *frc = 0;
-            xmlXPathObjectPtr result;
-            int k, study_speed_base, attacks;
-            struct att *attack;
-            skill_t sk;
-
-            propValue = xmlGetProp(node, BAD_CAST "name");
-            assert(propValue != NULL);
-            rc = rc_get_or_create((const char *)propValue);
-            xmlFree(propValue);
-
-            propValue = xmlGetProp(node, BAD_CAST "damage");
-            assert(propValue != NULL);
-            rc->def_damage = str_strdup((const char *)propValue);
-            xmlFree(propValue);
-
-            rc->magres = frac_make(xml_ivalue(node, "magres", 100), 100);
-            rc->healing = (int)(xml_fvalue(node, "healing", rc->healing) * 100); /* TODO: store as int in XML */
-            rc->maxaura = (int)(xml_fvalue(node, "maxaura", rc->maxaura) * 100); /* TODO: store as int in XML */
-            rc->regaura = (float)xml_fvalue(node, "regaura", rc->regaura);
-            rc->recruitcost = xml_ivalue(node, "recruitcost", rc->recruitcost);
-            rc->maintenance = xml_ivalue(node, "maintenance", rc->maintenance);
-            rc->weight = xml_ivalue(node, "weight", rc->weight);
-            rc->capacity = xml_ivalue(node, "capacity", rc->capacity);
-            rc->income = xml_ivalue(node, "income", rc->income);
-            rc->speed = (float)xml_fvalue(node, "speed", rc->speed);
-            rc->hitpoints = xml_ivalue(node, "hp", rc->hitpoints);
-            rc->armor = xml_ivalue(node, "ac", rc->armor);
-            study_speed_base = xml_ivalue(node, "studyspeed", 0);
-            if (study_speed_base != 0) {
-                for (sk = 0; sk < MAXSKILLS; ++sk) {
-                    set_study_speed(rc, sk, study_speed_base);
-                }
-            }
-
-            rc->at_default = (char)xml_ivalue(node, "unarmedattack", rc->at_default);
-            rc->df_default = (char)xml_ivalue(node, "unarmeddefense", rc->df_default);
-            rc->at_bonus = (char)xml_ivalue(node, "attackmodifier", rc->at_bonus);
-            rc->df_bonus = (char)xml_ivalue(node, "defensemodifier", rc->df_bonus);
-
-            if (!xml_bvalue(node, "teach", true))
-                rc->flags |= RCF_NOTEACH;
-            if (!xml_bvalue(node, "cansteal", true))
-                rc->flags |= RCF_NOSTEAL;
-            if (!xml_bvalue(node, "learn", true))
-                rc->flags |= RCF_NOLEARN;
-            if (xml_bvalue(node, "playerrace", false)) {
-                assert(rc->recruitcost == 0);
-                rc->flags |= RCF_PLAYABLE;
-            }
-            if (xml_bvalue(node, "scarepeasants", false))
-                rc->flags |= RCF_SCAREPEASANTS;
-            if (xml_bvalue(node, "cansail", true))
-                rc->flags |= RCF_CANSAIL;
-            if (xml_bvalue(node, "cannotmove", false))
-                rc->flags |= RCF_CANNOTMOVE;
-            if (xml_bvalue(node, "fly", false))
-                rc->flags |= RCF_FLY;
-            if (xml_bvalue(node, "invisible", false))
-                rc->flags |= RCF_INVISIBLE;
-            if (xml_bvalue(node, "coastal", false))
-                rc->flags |= RCF_COASTAL;
-            if (xml_bvalue(node, "unarmedguard", false))
-                rc->flags |= RCF_UNARMEDGUARD;
-            if (xml_bvalue(node, "swim", false))
-                rc->flags |= RCF_SWIM;
-            if (xml_bvalue(node, "walk", false))
-                rc->flags |= RCF_WALK;
-            if (xml_bvalue(node, "horse", false))
-                rc->flags |= RCF_HORSE;
-            if (xml_bvalue(node, "desert", false))
-                rc->flags |= RCF_DESERT;
-            if (xml_bvalue(node, "absorbpeasants", false))
-                rc->flags |= RCF_ABSORBPEASANTS;
-            if (xml_bvalue(node, "noheal", false))
-                rc->flags |= RCF_NOHEAL;
-            if (xml_bvalue(node, "noweapons", false))
-                rc->flags |= RCF_NOWEAPONS;
-            if (xml_bvalue(node, "shapeshift", false))
-                rc->flags |= RCF_SHAPESHIFT;
-            if (xml_bvalue(node, "shapeshiftany", false))
-                rc->flags |= RCF_SHAPESHIFTANY;
-            if (xml_bvalue(node, "illusionary", false))
-                rc->flags |= RCF_ILLUSIONARY;
-            if (xml_bvalue(node, "undead", false))
-                rc->flags |= RCF_UNDEAD;
-            if (xml_bvalue(node, "dragon", false))
-                rc->flags |= RCF_DRAGON;
-            if (xml_bvalue(node, "shipspeed", false))
-                rc->flags |= RCF_SHIPSPEED;
-
-            if (xml_bvalue(node, "giveperson", false))
-                rc->ec_flags |= ECF_GIVEPERSON;
-            if (xml_bvalue(node, "giveunit", false))
-                rc->ec_flags |= ECF_GIVEUNIT;
-            if (xml_bvalue(node, "getitem", false))
-                rc->ec_flags |= ECF_GETITEM;
-            if (xml_bvalue(node, "recruitethereal", false))
-                rc->ec_flags |= ECF_REC_ETHEREAL;
-            if (xml_bvalue(node, "recruitunlimited", false))
-                rc->ec_flags |= ECF_REC_UNLIMITED;
-            if (xml_bvalue(node, "stonegolem", false))
-                rc->ec_flags |= ECF_STONEGOLEM;
-            if (xml_bvalue(node, "irongolem", false))
-                rc->ec_flags |= ECF_IRONGOLEM;
-
-            if (xml_bvalue(node, "equipment", false))
-                rc->battle_flags |= BF_EQUIPMENT; /* TODO: invert this flag, so rc_get_or_create gets simpler */
-            if (xml_bvalue(node, "noblock", false))
-                rc->battle_flags |= BF_NOBLOCK;
-            if (xml_bvalue(node, "invinciblenonmagic", false))
-                rc->battle_flags |= BF_INV_NONMAGIC;
-            if (xml_bvalue(node, "resistbash", false))
-                rc->battle_flags |= BF_RES_BASH;
-            if (xml_bvalue(node, "resistcut", false))
-                rc->battle_flags |= BF_RES_CUT;
-            if (xml_bvalue(node, "resistpierce", false))
-                rc->battle_flags |= BF_RES_PIERCE;
-            if (xml_bvalue(node, "noattack", false))
-                rc->battle_flags |= BF_NO_ATTACK;
-
-            rc->recruit_multi = 1.0;
-            for (child = node->children; child; child = child->next) {
-                if (strcmp((const char *)child->name, "ai") == 0) {
-                    parse_ai(rc, child);
-                }
-                else if (strcmp((const char *)child->name, "param") == 0) {
-                    xmlChar *propName = xmlGetProp(child, BAD_CAST "name");
-                    xmlChar *propValue = xmlGetProp(child, BAD_CAST "value");
-                    rc_set_param(rc, (const char *)propName, (const char *)propValue);
-                    xmlFree(propName);
-                    xmlFree(propValue);
-                }
-            }
-
-            /* reading eressea/races/race/skill */
-            xpath->node = node;
-            result = xmlXPathEvalExpression(BAD_CAST "skill", xpath);
-            memset(rc->bonus, 0, sizeof(rc->bonus));
-            for (k = 0; k != result->nodesetval->nodeNr; ++k) {
-                xmlNodePtr node = result->nodesetval->nodeTab[k];
-                int mod = xml_ivalue(node, "modifier", 0);
-                int speed = xml_ivalue(node, "speed", study_speed_base);
-
-                propValue = xmlGetProp(node, BAD_CAST "name");
-                assert(propValue != NULL);
-                sk = findskill((const char *)propValue);
-                if (sk != NOSKILL) {
-                    rc->bonus[sk] = (char)mod;
-                    if (speed) {
-                        set_study_speed(rc, sk, speed);
-                    }
-                }
-                else {
-                    log_error("unknown skill '%s' in race '%s'\n", (const char *)propValue, rc->_name);
-                }
-                xmlFree(propValue);
-            }
-            xmlXPathFreeObject(result);
-
-            /* reading eressea/races/race/familiar */
-            xpath->node = node;
-            result = xmlXPathEvalExpression(BAD_CAST "familiar", xpath);
-            if (result->nodesetval->nodeNr > MAXMAGIETYP) {
-                log_error("race %s has %d potential familiars", rc->_name, result->nodesetval->nodeNr);
-            }
-            else {
-                for (k = 0; k != MAXMAGIETYP; ++k) {
-                    if (k < result->nodesetval->nodeNr) {
-                        xmlNodePtr node = result->nodesetval->nodeTab[k];
-
-                        propValue = xmlGetProp(node, BAD_CAST "race");
-                        assert(propValue != NULL);
-                        frc = rc_get_or_create((const char *)propValue);
-                        frc->flags |= RCF_FAMILIAR;
-                        rc->familiars[k] = frc;
-                        xmlFree(propValue);
-                    }
-                    else {
-                        rc->familiars[k] = frc;
-                    }
-                }
-            }
-            xmlXPathFreeObject(result);
-
-            /* reading eressea/races/race/attack */
-            xpath->node = node;
-            result = xmlXPathEvalExpression(BAD_CAST "attack", xpath);
-            attack = rc->attack;
-            attacks = 0;
-            for (k = 0; k != result->nodesetval->nodeNr; ++k) {
-                xmlNodePtr node = result->nodesetval->nodeTab[k];
-                while (attack->type != AT_NONE) {
-                    ++attack;
-                    if (attacks++ >= RACE_ATTACKS) {
-                        log_error("too many attacks for race '%s'\n", rc->_name);
-                        assert(!"aborting");
-                    }
-                }
-
-                propValue = xmlGetProp(node, BAD_CAST "damage");
-                if (propValue != NULL) {
-                    attack->data.dice = str_strdup((const char *)propValue);
-                    xmlFree(propValue);
-                }
-                else {
-                    attack->data.sp = xml_spellref(node, "spell");
-                    if (attack->data.sp) {
-                        attack->level = xml_ivalue(node, "level", 0);
-                        if (attack->level <= 0) {
-                            log_error("magical attack '%s' for race '%s' needs a level: %d\n",
-                                spellref_name(attack->data.sp), rc->_name, attack->level);
-                        }
-                    }
-                }
-                attack->type = xml_ivalue(node, "type", 0);
-                attack->flags = xml_ivalue(node, "flags", 0);
-            }
-            xmlXPathFreeObject(result);
-        }
-    }
-    xmlXPathFreeObject(races);
-
-    xmlXPathFreeContext(xpath);
-
-    return results;
-}
-
-static int parse_messages(xmlDocPtr doc)
-{
-    xmlXPathContextPtr xpath;
-    xmlXPathObjectPtr messages;
-    xmlNodeSetPtr nodes;
-    int i, results;
-
-    xpath = xmlXPathNewContext(doc);
-
-    /* reading eressea/messages/message */
-    messages =
-        xmlXPathEvalExpression(BAD_CAST "/eressea/messages/message", xpath);
-    nodes = messages->nodesetval;
-    results = nodes->nodeNr;
-    for (i = 0; i != nodes->nodeNr; ++i) {
-        xmlNodePtr node = nodes->nodeTab[i];
-        const char *default_section = "events";
-        xmlChar *propSection;
-        xmlChar *propValue;
-        xmlXPathObjectPtr result;
-        int nargs = 0;
-        char **argv = NULL;
-        const message_type *mtype;
-
-        /* arguments */
-        xpath->node = node;
-        result = xmlXPathEvalExpression(BAD_CAST "type/arg", xpath);
-        if (result->nodesetval && result->nodesetval->nodeNr > 0) {
-            int k;
-            nargs = result->nodesetval->nodeNr;
-            argv = malloc(sizeof(char *) * (nargs + 1));
-            for (k = 0; k != nargs; ++k) {
-                xmlNodePtr node = result->nodesetval->nodeTab[k];
-                char zBuffer[128];
-                xmlChar *propName, *propType;
-
-                propName = xmlGetProp(node, BAD_CAST "name");
-                propType = xmlGetProp(node, BAD_CAST "type");
-                sprintf(zBuffer, "%s:%s", (const char *)propName,
-                    (const char *)propType);
-                xmlFree(propName);
-                xmlFree(propType);
-                argv[k] = str_strdup(zBuffer);
-            }
-            argv[nargs] = NULL;
-        }
-        xmlXPathFreeObject(result);
-
-        /* add the messagetype */
-        propSection = xmlGetProp(node, BAD_CAST "section");
-        if (propSection == NULL) {
-            propSection = BAD_CAST default_section;
-        }
-
-        propValue = xmlGetProp(node, BAD_CAST "name");
-        mtype = mt_find((const char *)propValue);
-        if (mtype == NULL) {
-            mtype = mt_create(mt_new((const char *)propValue, (const char *)propSection), (const char **)argv, nargs);
-        }
-        else {
-            assert(argv != NULL || !"cannot redefine arguments of message now");
-        }
-        xmlFree(propValue);
-
-        if (propSection != BAD_CAST default_section) {
-            xmlFree(propSection);
-        }
-
-        /* register the type for CR and NR */
-        crt_register(mtype);
-        nrt_register(mtype);
-
-        /* let's clean up the mess */
-        if (argv != NULL) {
-            int k;
-            for (k = 0; argv[k] != NULL; ++k) {
-                free(argv[k]);
-            }
-            free(argv);
-        }
-    }
-
-    xmlXPathFreeObject(messages);
-
-    xmlXPathFreeContext(xpath);
-    return results;
-}
-
-void register_xmlreader(void)
-{
-#ifndef _MSC_VER /* gcc and clang complain about unused function */
-    xml_register_callback(parse_resources);
-    xml_register_callback(parse_buildings);
-    xml_register_callback(parse_ships);
-    xml_register_callback(parse_spellbooks);
-    xml_register_callback(parse_spells);
-    xml_register_callback(parse_races);
-#endif
-
-
-    xml_register_callback(parse_messages);
-}
diff --git a/src/xmlreader.h b/src/xmlreader.h
deleted file mode 100644
index 290b785c3..000000000
--- a/src/xmlreader.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* 
-+-------------------+
-|                   |  Enno Rehling <enno@eressea.de>
-| Eressea PBEM host |  Christian Schlittchen <corwin@amber.kn-bremen.de>
-| (c) 1998 - 2007   |  Katja Zedel <katze@felidae.kn-bremen.de>
-|                   |  Henning Peters <faroul@beyond.kn-bremen.de>
-+-------------------+
-
-This program may not be used, modified or distributed
-without prior permission by the authors of Eressea.
-*/
-
-#ifndef H_KRNL_XMLREADER_H
-#define H_KRNL_XMLREADER_H
-
-struct spell;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-    extern void register_xmlreader(void);
-
-    /* game-specific callbacks */
-    extern void(*set_spelldata_cb) (struct spell * sp);
-#ifdef __cplusplus
-}
-#endif
-#endif

From bbae56633bed1f885f79176062f94e094e08ff40 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 18 May 2018 21:18:55 +0200
Subject: [PATCH 54/59] rules was part of convert, and we do never finished
 that branch.

---
 src/kernel/CMakeLists.txt |  1 -
 src/kernel/rules.c        | 12 ------------
 src/kernel/rules.h        |  5 -----
 3 files changed, 18 deletions(-)
 delete mode 100644 src/kernel/rules.c
 delete mode 100644 src/kernel/rules.h

diff --git a/src/kernel/CMakeLists.txt b/src/kernel/CMakeLists.txt
index 59b8cb806..86c2fb90c 100644
--- a/src/kernel/CMakeLists.txt
+++ b/src/kernel/CMakeLists.txt
@@ -69,7 +69,6 @@ pool.c
 race.c
 region.c
 resources.c
-rules.c
 save.c
 ship.c
 skills.c
diff --git a/src/kernel/rules.c b/src/kernel/rules.c
deleted file mode 100644
index c7499fe0c..000000000
--- a/src/kernel/rules.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <platform.h>
-#include "rules.h"
-
-int write_rules(const char *filename) {
-    return -1;
-}
-
-int read_rules(const char *filename)
-{
-    return -1;
-}
-
diff --git a/src/kernel/rules.h b/src/kernel/rules.h
deleted file mode 100644
index 98f0bf240..000000000
--- a/src/kernel/rules.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma once
-
-int read_rules(const char *filename);
-int write_rules(const char * filename);
-

From c11a0208460ff3ffed954ea086771954a6cd2de1 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 18 May 2018 21:24:08 +0200
Subject: [PATCH 55/59] remove the text from messages.xml

---
 res/core/messages.xml | 1878 -----------------------------------------
 src/exparse.c         |    2 +-
 2 files changed, 1 insertion(+), 1879 deletions(-)

diff --git a/res/core/messages.xml b/res/core/messages.xml
index b8f8125dc..757243d9f 100644
--- a/res/core/messages.xml
+++ b/res/core/messages.xml
@@ -2,58 +2,32 @@
 <eressea>
 <messages>
   <message name="nr_insectwinter" section="nr">
-    <text locale="de">Es ist Winter, und Insekten können nur in Wüsten oder mit Hilfe des Nestwärme-Tranks Personen rekrutieren.</text>
-    <text locale="en">It is winter, and insects can only recruit in deserts or with the aid of nestwarmth potions.</text>
   </message>
   <message name="nr_insectfall" section="nr">
-    <text locale="de">Es ist Spätherbst, und diese Woche ist die letzte vor dem Winter, in der Insekten rekrutieren können.</text>
-    <text locale="en">It is the last week before winter in which insects can still recruit.</text>
   </message>
   <message name="newbie_info_game" section="events">
     <type>
       <arg name="subject" type="string"/>
       <arg name="email" type="string"/>
     </type>
-      <text locale="de">Bitte denke daran, deine Befehle mit dem Betreff
-      $subject an $email zu senden.</text>
-      <text locale="en">Remember to send your orders to
-      $email with the subject ${subject}.</text>
   </message>
   <message name="parse_error" section="errors">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="command" type="string"/>
     </type>
-    <text locale="de">"$unit($unit): '$command' - Dieser Befehl ist unbekannt."</text>
-    <text locale="en">"$unit($unit): '$command' - Parse error, unknown command."</text>
   </message>
   <message name="reduced_production">
-    <text locale="de">Die Region ist verwüstet, der Boden karg.</text>
-    <text locale="en">The region is ravaged, the ground infertile.</text>
   </message>
   <message name="santa_f" section="events">
     <type>
       <arg name="item" type="resource"/>
     </type>
-    <text locale="de">'Ho ho ho!' Ein dicker Gnom fliegt auf einem von
-    8 Jungdrachen gezogenen Schlitten durch die Nacht und vermacht Deiner
-    Partei eine $resource($item,1). (Um diesen Gegenstand einer Einheit zu geben, gib
-    ihr den Befehl 'BEANSPRUCHE 1 $resource($item,1)').</text>
-    <text locale="en">'Ho ho ho!' A fat little gnome Gnom on a sled
-    pulled by 8 young dragons flies through the stary night and presents
-    your faction with a $resource($item,1).</text>
   </message>
   <message name="santa_m" section="events">
     <type>
       <arg name="item" type="resource"/>
     </type>
-    <text locale="de">'Ho ho ho!' Ein dicker Gnom fliegt auf einem von
-    8 Jungdrachen gezogenen Schlitten durch die Nacht und vermacht Deiner
-    Partei einen $resource($item,1). (Um diesen Gegenstand einer Einheit zu geben, gib
-    ihr den Befehl 'BEANSPRUCHE 1 $resource($item,1)').</text>
-    <text locale="en">'Ho ho ho!' A fat little gnome Gnom on a sled
-    pulled by 8 young dragons flies through the stary night and presents
-    your faction with a $resource($item,1).</text>
   </message>
 
   <message name="target_region_invalid">
@@ -62,8 +36,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Ungültige Zielregion."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - invalid target region."</text>
   </message>
   
   <message name="missing_direction">
@@ -72,8 +44,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - keine Richtung angegeben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - no direction was specified."</text>
   </message>
   
   <message name="target_region_not_empty">
@@ -82,8 +52,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - In der Zielregion befinden sich noch Einheiten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There are units in the target region."</text>
   </message>
   
   <message name="force_leave_ship" section="events">
@@ -92,8 +60,6 @@
       <arg name="owner" type="unit"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">$unit($owner) bittet $unit($unit), $ship($ship) zu verlassen.</text>
-    <text locale="en">$unit($owner) asks $unit($unit) to leave $ship($ship).</text>
   </message>
   <message name="force_leave_building" section="events">
     <type>
@@ -101,15 +67,11 @@
       <arg name="owner" type="unit"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">$unit($owner) bittet $unit($unit), $building($building) zu verlassen.</text>
-    <text locale="en">$unit($owner) asks $unit($unit) to leave $building($building).</text>
   </message>
   <message name="nr_claims" section="nr">
     <type>
       <arg name="items" type="items"/>
     </type>
-    <text locale="de">"Einheiten können die folgenden Gegenstände beanspruchen: $resources($items)"</text>
-    <text locale="en">"Units can claim the following items: $resources($items)"</text>
   </message>
   <message name="sighting" section="events">
     <type>
@@ -117,67 +79,45 @@
       <arg name="number" type="int"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$if($isnull($region),"Es","In $region($region)") wurde$if($eq($number,1),"","n") $int($number) $race($race,$number) gesichtet."</text>
-    <text locale="en">"$if($isnull($region),"","In $region($region), ")$int($number) $race($race,$number) were discovered."</text>
   </message>
   <message name="mallorn_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) läßt einen Teil seiner selbst in die Erde fliessen. Die Bäume, die Transformation überlebt haben, erscheinen nun viel kräftiger."</text>
-    <text locale="en">"The power of $unit($mage) flows into the ground and the trees which survived the spell appear much stronger now."</text>
   </message>
   <message name="flying_ship_result" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"$unit($mage) beschwört einen Luftgeist, der die $ship($ship) in die Wolken hebt."</text>
-    <text locale="en">"$unit($mage) summons a wind spirit that lifts the $ship($ship) into the clouds."</text>
   </message>
   <message name="confusion_result" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) beschwört einen Schleier der Verwirrung."</text>
-    <text locale="en">"$unit($mage) summons a fog of confusion."</text>
   </message>
 
   <message name="curseinfo::Feuerwand">
     <type><arg name="id" type="int"/></type>
-    <text locale="de">Eine Feuerwand blockiert die Ein- und Ausreise. ($int36($id))</text>
-    <text locale="en">A wall of fire blocks entry and exit. ($int36($id))</text>
   </message>
 
   <message name="curseinfo::magicboost">
     <type><arg name="id" type="int"/></type>
-    <text locale="de">Der Magier besitzt die Gabe des Chaos. ($int36($id))</text>
-    <text locale="en">The magician possesses the gift of Chaos. ($int36($id))</text>
   </message>
   <message name="curseinfo::slavery">
     <type><arg name="id" type="int"/></type>
-    <text locale="de">Dieser mächtige Bann scheint die Einheit ihres freien Willens zu berauben. Solange der Zauber wirkt, wird sie nur den Befehlen ihres neuen Herrn gehorchen. ($int36($id))</text>
-    <text locale="en">This powerful curse appears to rob the unit of its free will. As long as the curse is active, it will only obey the orders of its new lord. ($int36($id))</text>
   </message>
   <message name="curseinfo::calmmonster">
     <type><arg name="id" type="int"/></type>
-    <text locale="de">Dieser Beeinflussungszauber scheint die Einheit einem ganz bestimmten Volk wohlgesonnen zu machen. ($int36($id))</text>
-    <text locale="en">This enchantment appears to make the unit well-disposed towards a particular faction. ($int36($id))</text>
   </message>
   <message name="curseinfo::maelstrom">
     <type><arg name="id" type="int"/></type>
-    <text locale="de">Der Mahlstrom in dieser Region wird alle Schiffe, die in seinen Sog geraten, schwer beschädigen. ($int36($id))</text>
-    <text locale="en">The maelstrom in this area will heavily damage all ships coming into its wake. ($int36($id))</text>
   </message>
   <message name="curseinfo::healingzone">
     <type><arg name="id" type="int"/></type>
-    <text locale="de">Heilung ist in dieser Region magisch beeinflusst. ($int36($id))</text>
-    <text locale="en">Healing in this region is affected by magic. ($int36($id))</text>
   </message>
   <message name="curseinfo::shipdisorientation">
     <type><arg name="id" type="int"/></type>
-    <text locale="de">Dieses Schiff hat sich verfahren. ($int36($id))</text>
-    <text locale="en">This ship has lost its path. ($int36($id))</text>
   </message>
 
   <message name="curseinfo::sparkle_1" section="events">
@@ -185,151 +125,113 @@
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) ist im Traum eine Fee erschienen. ($int36($id))"</text>
-    <text locale="en">"In a dream, a fairy appears to $unit($unit). ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_2" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) wird von bösen Alpträumen geplagt. ($int36($id))"</text>
-    <text locale="en">"$unit($unit) is haunted by terrbile nightmares. ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_3" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) wird von einem glitzernden Funkenregen umgeben. ($int36($id))"</text>
-    <text locale="en">"$unit($unit) is surrounded by a shower of glittering sparkles. ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_4" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Ein schimmernder Lichterkranz umgibt $unit($unit). ($int36($id))"</text>
-    <text locale="en">"A circle of shimmering lights surrounds $unit($unit). ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_5" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Eine Melodie erklingt, und $unit($unit) tanzt bis spät in die Nacht hinein. ($int36($id))"</text>
-    <text locale="en">"A haunting melody fills the air, and $unit($unit) dances until late into the night. ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_6" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) findet eine kleine Flöte, die eine wundersame Melodie spielt. ($int36($id))"</text>
-    <text locale="en">"$unit($unit) finds a small flute that plays a beautiful melody. ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_7" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die Frauen des nahegelegenen Dorfes bewundern $unit($unit) verstohlen. ($int36($id))"</text>
-    <text locale="en">"The women of the nearby village cast furtive looks at $unit($unit). ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_8" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Eine Gruppe vorbeiziehender Bergarbeiter rufen $unit($unit) eindeutig Zweideutiges nach. ($int36($id))"</text>
-    <text locale="en">"A group of passing miners makes passes at $unit($unit). ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_9" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) bekommt von einer Schlange einen Apfel angeboten. ($int36($id))"</text>
-    <text locale="en">"A large green snake offers $unit($unit) a fine-looking apple. ($int36($id))"</text>
   </message>
   <message name="curseinfo::antimagiczone" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="en">"A spell is deflecting magical energies and weakening all other spells cast in the region. ($int36($id))"</text>
-    <text locale="de">"Dieser Zauber scheint magische Energien irgendwie abzuleiten und so alle in der Region gezauberten Sprüche in ihrer Wirkung zu schwächen oder ganz zu verhindern. ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_10" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Ein Einhorn berührt $unit($unit) mit seinem Horn und verschwindet kurz darauf im Unterholz. ($int36($id))"</text>
-    <text locale="en">"A unicorn touches $unit($unit) with its horn and vanishes into the forest quickly after. ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_11" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Vogelzwitschern begleitet $unit($unit) auf all seinen Wegen. ($int36($id))"</text>
-    <text locale="en">"Bird songs follow $unit($unit) on all his travels. ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_12" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Leuchtende Blumen erblühen rund um das Lager von $unit($unit). ($int36($id))"</text>
-    <text locale="en">"Brightly coloured flowers pop up all around $unit($unit)'s camp. ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_13" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Über $unit($unit) zieht eine Gruppe Geier ihre Kreise. ($int36($id))"</text>
-    <text locale="en">"A group of vultures circles above $unit($unit). ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_14" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Der Kopf von $unit($unit) hat sich in einen grinsenden Totenschädel verwandelt. ($int36($id))"</text>
-    <text locale="en">"The head of $unit($unit) has turned into a madly grinning skull. ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_15" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Ratten folgen $unit($unit) auf Schritt und Tritt. ($int36($id))"</text>
-    <text locale="en">"Rats follow $unit($unit)'s every step. ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_16" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Pestbeulen befallen den Körper von $unit($unit). ($int36($id))"</text>
-    <text locale="en">"The body of $unit($unit) is disfigured by hideous boils. ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_17" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Eine dunkle Fee erscheint $unit($unit) im Schlaf. Sie ist von schauriger Schönheit. ($int36($id))"</text>
-    <text locale="en">"A dark and mysterious fairy appears before $unit($unit). She is of bewitching beauty. ($int36($id))"</text>
   </message>
   <message name="curseinfo::sparkle_18" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Fäulnisgeruch dringt $unit($unit) aus allen Körperöffnungen. ($int36($id))"</text>
-    <text locale="en">"The stench of decay is poring from all the orifices of $unit($unit). ($int36($id))"</text>
   </message>
   <message name="curseinfo::calm_1" section="events">
     <type>
@@ -337,8 +239,6 @@
       <arg name="faction" type="faction"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) scheint $faction($faction) zu mögen. ($int36($id))"</text>
-    <text locale="en">"$unit($unit) likes $faction($faction). ($int36($id))"</text>
   </message>
   <message name="curseinfo::calm_0" section="events">
     <type>
@@ -346,8 +246,6 @@
       <arg name="race" type="race"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) scheint $race($race, 0) zu mögen. ($int36($id))"</text>
-    <text locale="en">"$unit($unit) seems to like $race($race, 0). ($int36($id))"</text>
   </message>
   <message name="curseinfo::skill_2" section="events">
     <type>
@@ -355,8 +253,6 @@
       <arg name="skill" type="skill"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) ist ungewöhnlich ungeschickt in $skill($skill). ($int36($id))"</text>
-    <text locale="en">"$unit($unit) has some troubles with $skill($skill). ($int36($id))"</text>
   </message>
   <message name="curseinfo::skill_1" section="events">
     <type>
@@ -364,8 +260,6 @@
       <arg name="skill" type="skill"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) ist ungewöhnlich geschickt in $skill($skill). ($int36($id))"</text>
-    <text locale="en">"$unit($unit) is incredibly skilled at $skill($skill). ($int36($id))"</text>
   </message>
   <message name="curseinfo::slave_1" section="events">
     <type>
@@ -373,8 +267,6 @@
       <arg name="duration" type="int"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) wird noch $int($duration) $if($eq($duration,1), "Woche", "Wochen") unter unserem Bann stehen. ($int36($id))"</text>
-    <text locale="en">"$unit($unit) will be under our influence for $int($duration) more $if($eq($duration,1), "week", "weeks"). ($int36($id))"</text>
   </message>
   <message name="curseinfo::speed_1" section="events">
     <type>
@@ -383,8 +275,6 @@
       <arg name="duration" type="int"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$int($number) $if($eq($number,1), "Person", "Personen") von $unit($unit) $if($eq($number,1), "ist", "sind") noch $int($duration) $if($eq($duration,1), "Woche", "Wochen") beschleunigt. ($int36($id))"</text>
-    <text locale="en">"$int($number) $if($eq($number,1), "member", "members") of $unit($unit) $if($eq($number,1), "is", "are") accelerated for $int($duration) more $if($eq($duration,1), "week", "weeks"). ($int36($id))"</text>
   </message>
   <message name="curseinfo::warmth_1" section="events">
     <type>
@@ -392,270 +282,196 @@
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$int($number) $if($eq($number,1), "Person", "Personen") von $unit($unit) $if($eq($number,1), "fühlt", "fühlen") sich vor Kälte geschützt. ($int36($id))"</text>
-    <text locale="en">"$int($number) $if($eq($number,1), "member", "members") of $unit($unit) $if($eq($number,1), "is", "are") protected from the cold. ($int36($id))"</text>
   </message>
   <message name="curseinfo::ship_unknown" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Ein unbekannter Zauber liegt auf dem Schiff. ($int36($id))"</text>
-    <text locale="en">"An unknown spell lies on this ship. ($int36($id))"</text>
   </message>
   <message name="curseinfo::unit_unknown" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Ein unbekannter Zauber liegt auf der Einheit. ($int36($id))"</text>
-    <text locale="en">"An unknown spell lies on this unit. ($int36($id))"</text>
   </message>
   <message name="curseinfo::building_unknown" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Ein unbekannter Zauber liegt auf dem Gebäude. ($int36($id))"</text>
-    <text locale="en">"An unknown spell lies on this building. ($int36($id))"</text>
   </message>
   <message name="curseinfo::region_unknown" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Ein unbekannter Zauber liegt auf der Region. ($int36($id))"</text>
-    <text locale="en">"An unknown spell lies on this region. ($int36($id))"</text>
   </message>
   <message name="curseinfo::riotzone" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Eine Wolke negativer Energie liegt über der Region. ($int36($id))"</text>
-    <text locale="en">"A fog of negative energy enshrouds the region. ($int36($id))"</text>
   </message>
   <message name="curseinfo::strength" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die Leute strotzen nur so vor Kraft. ($int36($id))"</text>
-    <text locale="en">"Testosterone levels are at an all-time high. ($int36($id))"</text>
   </message>
   <message name="curseinfo::worse" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) wird von einem Alp geritten. ($int36($id))"</text>
-    <text locale="en">"$unit($unit) is chased by a nightmare. ($int36($id))"</text>
   </message>
   <message name="curseinfo::orcish" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) stürzt sich von einem amourösen Abenteuer ins nächste. ($int36($id))"</text>
-    <text locale="en">"$unit($unit) goes from one amourous adventure to another. ($int36($id))"</text>
   </message>
   <message name="curseinfo::fumble" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) kann sich kaum konzentrieren. ($int36($id))"</text>
-    <text locale="en">"$unit($unit) can hardly focus on anything. ($int36($id))"</text>
   </message>
   <message name="curseinfo::itemcloak" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die Ausrüstung von $unit($unit) scheint unsichtbar. ($int36($id))"</text>
-    <text locale="en">"$unit($unit)'s equipment is invisible. ($int36($id))"</text>
   </message>
   <message name="magicresistance_unit" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die natürliche Widerstandskraft gegen Verzauberung ist gestärkt. ($int36($id))"</text>
-    <text locale="en">"The magical resistance has been strengthened. ($int36($id))"</text>
   </message>
   <message name="magicresistance_building" section="events">
     <type>
       <arg name="building" type="building"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die natürliche Widerstandskraft gegen Verzauberung ist gestärkt. ($int36($id))"</text>
-    <text locale="en">"The magical resistance has been strengthened. ($int36($id))"</text>
   </message>
   <message name="curseinfo::goodmagicresistancezone" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die natürliche Widerstandskraft gegen Verzauberung bestimmter Einheiten in dieser Region wurde gestärkt. ($int36($id))"</text>
-    <text locale="en">"The magical resistance of some units in this region was boosted. ($int36($id))"</text>
   </message>
   <message name="curseinfo::badmagicresistancezone" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die natürliche Widerstandskraft gegen Verzauberung bestimmter Einheiten in dieser Region wurde geschwächt. ($int36($id))"</text>
-    <text locale="en">"The magical resistance of some units in this region was weakened. ($int36($id))"</text>
   </message>
   <message name="curseinfo::magicwalls" section="events">
     <type>
       <arg name="building" type="building"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Diese Mauern wirken, als wären sie direkt aus der Erde gewachsen und nicht erbaut. ($int36($id))"</text>
-    <text locale="en">"These walls appear to have grown straight out of the earth. ($int36($id))"</text>
   </message>
   <message name="curseinfo::buildingunknown" section="events">
     <type>
       <arg name="building" type="building"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Ein magischer Schimmer liegt auf diesen Mauern. ($int36($id))"</text>
-    <text locale="en">"A magical shimmer lies on these walls. ($int36($id))"</text>
   </message>
   <message name="curseinfo::magicstreetwarn" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die Straßen sind erstaunlich trocken und gut begehbar, doch an manchen Stellen bilden sich wieder die erste Schlammlöcher. ($int36($id))"</text>
-    <text locale="en">"The roads are extremely dry and well-kept, but some areas show the first signs of potholes reappearing. ($int36($id))"</text>
   </message>
   <message name="curseinfo::magicstreet" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die Straßen sind erstaunlich trocken und gut begehbar. ($int36($id))"</text>
-    <text locale="en">"The roads are extremely dry and well-kept. ($int36($id))"</text>
   </message>
   <message name="curseinfo::baddream" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Albträume plagen die Leute. ($int36($id))"</text>
-    <text locale="en">"Nightmares plague the population. ($int36($id))"</text>
   </message>
   <message name="curseinfo::gooddream" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die Leute haben schöne Träume. ($int36($id))"</text>
-    <text locale="en">"The people in this region have sweet dreams. ($int36($id))"</text>
   </message>
   <message name="curseinfo::godcurseocean" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Diese Region wurde von den Göttern verflucht. Das Meer ist eine ekelige Brühe, braunschwarze, stinkende Gase steigen aus den unergründlichen Tiefen hervor, und untote Seeungeheuer, Schiffe zerfressend und giftige grüne Galle geifernd, sind der Schrecken aller Seeleute, die diese Gewässer durchqueren. Niemand kann hier lange überleben. ($int36($id))"</text>
-    <text locale="en">"This region was cursed by the gods. The sea is a foul cesspool, noxious gases rise from the deep, undead seamonsters attack all ships. Noone can live here for long. ($int36($id))"</text>
   </message>
   <message name="curseinfo::godcurse" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Diese Region wurde von den Göttern verflucht. Stinkende Nebel ziehen über die tote Erde und furchtbare Kreaturen ziehen über das Land. Die Brunnen sind vergiftet, und die wenigen essbaren Früchte sind von einem rosa Pilz überzogen. Niemand kann hier lange überleben. ($int36($id))"</text>
-    <text locale="en">"This region was cursed by the gods. Stinking vapors billow over the dead ground and hideous creatures move about the country. The wells are poisened and the edible plants are covered by a pink fungus. Noone can live here for long. ($int36($id))"</text>
   </message>
   <message name="curseinfo::disorientationzone" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Ein Schleier der Verwirrung liegt über der Region. ($int36($id))"</text>
-    <text locale="en">"A veil of confusion lies over the region. ($int36($id))"</text>
   </message>
   <message name="curseinfo::deathcloud" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"In der Region treibt ein Giftelementar sein Unwesen. ($int36($id))"</text>
-    <text locale="en">"A poison elemental is spreading pestilence and death. ($int36($id))"</text>
   </message>
   <message name="curseinfo::peacezone" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die ganze Region ist von einer friedlichen Stimmung erfasst. ($int36($id))"</text>
-    <text locale="en">"Everyone in this region seems to be in a peacful mood. ($int36($id))"</text>
   </message>
   <message name="curseinfo::generous" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Es herrscht eine fröhliche und ausgelassene Stimmung. ($int36($id))"</text>
-    <text locale="en">"Everyone in this region seems to be having a very good time. ($int36($id))"</text>
   </message>
   <message name="curseinfo::depression" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die Bauern sind unzufrieden. ($int36($id))"</text>
-    <text locale="en">"The peasants are upset. ($int36($id))"</text>
   </message>
   <message name="curseinfo::badlearn" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Alle Leute in der Region haben Schlafstörungen. ($int36($id))"</text>
-    <text locale="en">"People in this region suffer from insomnia. ($int36($id))"</text>
   </message>
   <message name="curseinfo::drought" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"In dieser Gegend herrscht eine Dürre. ($int36($id))"</text>
-    <text locale="en">"This region was hit by a drought. ($int36($id))"</text>
   </message>
   <message name="curseinfo::blessedharvest" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"In dieser Gegend steht das Korn besonders gut im Feld. ($int36($id))"</text>
-    <text locale="en">"The grain in this region is especially healthy. ($int36($id))"</text>
   </message>
   <message name="curseinfo::shipspeedup" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die Winde scheinen dieses Schiff besonders zu beguenstigen. ($int36($id))"</text>
-    <text locale="en">"The winds seem to favor this ship. ($int36($id))"</text>
   </message>
   <message name="curseinfo::holyground" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Untote schrecken vor dieser Region zurück. ($int36($id))"</text>
-    <text locale="en">"The undead turn away from this region. ($int36($id))"</text>
   </message>
   <message name="curseinfo::nocostbuilding" section="events">
     <type>
       <arg name="id" type="int"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"Der Zahn der Zeit kann diesen Mauern nichts anhaben. ($int36($id))"</text>
-    <text locale="en">"Time cannot touch these walls. ($int36($id))"</text>
   </message>
   <message name="curseinfo::fogtrap" section="events">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Dichte Nebel bedecken diese Woche die Region. Keine Einheit schafft es, diese Nebel zu durchdringen und die Region zu verlassen. ($int36($id))"</text>
-    <text locale="en">"Heavy fog makes it impossible to leave the region. ($int36($id))"</text>
   </message>
   <message name="use_speedsail" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="speed" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) setzt ein Sonnensegel. Die Geschwindigkeit des Schiffes erhöht um $int($speed)."</text>
-    <text locale="en">"$unit($unit) sets a solar sail. The ship's speed is increased by $int($speed)."</text>
   </message>
   <message name="missing_message" section="errors">
     <type>
       <arg name="name" type="string"/>
     </type>
-    <text locale="de">"Interner Fehler: Meldung '$name' nicht definiert."</text>
-    <text locale="en">"Internal Error: Message '$name' is undefined."</text>
   </message>
   <message name="missing_feedback" section="errors">
     <type>
@@ -664,8 +480,6 @@
       <arg name="command" type="order"/>
       <arg name="name" type="string"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Interner Fehler: Meldung '$name' nicht definiert."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Internal Error: Message '$name' is undefined."</text>
   </message>
   <message name="use_questkey_wrongregion" section="events">
     <type>
@@ -673,8 +487,6 @@
       <arg name="unit" type="unit"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier ist kein passendes Schloss."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No fitting lock can be found here."</text>
   </message>
   <message name="questportal_unlock" section="events">
     <type>
@@ -682,8 +494,6 @@
       <arg name="unit" type="unit"/>
       <arg name="key" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) öffnet eines der Schlösser in $region($region) mit $if($eq($key,1),"dem Achatenen Schlüssel","dem Saphirnen Schlüssel")."</text>
-    <text locale="en">"$unit($unit) unlocks one of the locks in $region($region) with $if($eq($key,1),"the Agate Key","the Sapphire Key")."</text>
   </message>
   <message name="questportal_lock" section="events">
     <type>
@@ -691,31 +501,23 @@
       <arg name="unit" type="unit"/>
       <arg name="key" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) verschließt eines der Schlösser in $region($region) mit $if($eq($key,1),"dem Achatenen Schlüssel","dem Saphirnen Schlüssel")."</text>
-    <text locale="en">"$unit($unit) locks one of the locks in $region($region) with $if($eq($key,1),"the Agate Key","the Sapphire Key")."</text>
   </message>
   <message name="becomewere" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) verwandelt sich in ein Werwesen."</text>
-    <text locale="en">"$unit($unit) in $region($region) becomes a lycantrope."</text>
   </message>
   <message name="victory_murder_complete" section="events">
     <type>
       <arg name="winners" type="string"/>
       <arg name="n" type="int"/>
     </type>
-    <text locale="de">"SIEG! $if($eq($n,1), "Die Partei $winners hat", "Die Parteien $winners haben") die Siegbedingung für die erforderliche Zeit erfüllt. Das Spiel ist damit beendet."</text>
-    <text locale="en">"VICTORY! $if($eq($n,1), "The faction $winners has", "The factions $winners have") fulfilled the victory condition for the necessary time. The game is over."</text>
   </message>
   <message name="victory_murder_cfulfilled" section="events">
     <type>
       <arg name="faction" type="faction"/>
     </type>
-    <text locale="de">"Achtung: $faction($faction) hat die Siegbedingungen erfüllt und wird in $if($eq($remain,1),"einer Woche","$int($remain) Wochen") zum Sieger erklärt werden."</text>
-    <text locale="en">"Attention: $faction($faction) has fulfilled the victory condition and will be declared winner in $if($eq($remain,1),"one week","$int($remain) weeks")."</text>
   </message>
   <message name="killedbygm" section="events">
     <type>
@@ -723,8 +525,6 @@
       <arg name="string" type="string"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) wurde in $region($region) von einem GM gelöscht: \"$string\"."</text>
-    <text locale="en">"$unit($unit) in $region($region) was removed by a GM: \"$string\"."</text>
   </message>
   <message name="displayitem" section="events">
     <type>
@@ -732,14 +532,10 @@
       <arg name="description" type="string"/>
       <arg name="weight" type="int"/>
     </type>
-    <text locale="de">"$resource($item,1) (Gewicht: $weight($weight)): $description"</text>
-    <text locale="en">"$resource($item,1) (weight: $weight($weight)): $description"</text>
   </message>
   <message name="healall" section="events">
     <type>
   </type>
-    <text locale="de">"Ein Hauch des Lebens liegt über der Welt und alle Wesen fühlen sich frisch und erholt."</text>
-    <text locale="en">"Life itself touches the world and all beings are healed."</text>
   </message>
   <message name="lucky_item" section="events">
     <type>
@@ -747,16 +543,12 @@
       <arg name="item" type="resource"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) hat Glück und findet einen Hort von $int($amount) $resource($item,$amount)."</text>
-    <text locale="en">"$unit($unit) luckily finds a cache of $int($amount) $resource($item,$amount)."</text>
   </message>
   <message name="battle_critical" section="battle">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="index" type="int"/>
     </type>
-    <text locale="de">"$int36($unit.id($unit))/$int($index) erzielt einen kritischen Treffer."</text>
-    <text locale="en">"$int36($unit.id($unit))/$int($index) does critical damage."</text>
   </message>
   <message name="teach_asgood" section="errors">
     <type>
@@ -765,8 +557,6 @@
       <arg name="command" type="order"/>
       <arg name="student" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) muß mindestens 2 Stufen besser sein als $unit($student)."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) needs to be at least 2 levels better than $unit($student)."</text>
   </message>
   <message name="teach_nolearn" section="errors">
     <type>
@@ -775,8 +565,6 @@
       <arg name="command" type="order"/>
       <arg name="student" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($student) lernt nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($student) is not learning."</text>
   </message>
   <message name="build_required" section="errors">
     <type>
@@ -785,23 +573,17 @@
       <arg name="command" type="order"/>
       <arg name="required" type="resources"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dafür braucht die Einheit $resources($required)."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - For this, the unit needs $resources($required)."</text>
   </message>
   <message name="travelthru_trail" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">$trailto($region)</text>
-    <text locale="en">$trailto($region)</text>
   </message>
   <message name="nr_migrants" section="nr">
     <type>
       <arg name="units" type="int"/>
       <arg name="maxunits" type="int"/>
     </type>
-    <text locale="de">"Deine Partei hat $int($units) Migranten und kann maximal $int($maxunits) Migranten aufnehmen."</text>
-    <text locale="en">"Your faction has $int($units) migrants out of a possible total of $int($maxunits)."</text>
   </message>
   <message name="nr_alliance" section="nr">
     <type>
@@ -810,16 +592,12 @@
       <arg name="id" type="int"/>
       <arg name="age" type="int"/>
     </type>
-    <text locale="de">"Seit $int($age) Wochen Mitglied der Allianz '$name ($int36($id))', angeführt von $faction($leader)."</text>
-    <text locale="en">"Member of '$name ($int36($id))' for $int($age) weeks, led by $faction($leader)."</text>
   </message>
   <message name="nr_heroes" section="nr">
     <type>
       <arg name="units" type="int"/>
       <arg name="maxunits" type="int"/>
     </type>
-    <text locale="de">"Deine Partei hat $int($units) Helden und kann maximal $int($maxunits) Helden ernennen."</text>
-    <text locale="en">"Your faction has promoted $int($units) heroes out of a possible total of $int($maxunits)."</text>
   </message>
   <message name="nr_population" section="nr">
     <type>
@@ -827,180 +605,132 @@
       <arg name="limit" type="int"/>
       <arg name="units" type="int"/>
     </type>
-    <text locale="de">"Deine Partei hat $int($population) Personen in $int($units) von maximal $int($limit) Einheiten."</text>
-    <text locale="en">"Your faction has $int($population) people in $int($units) of $int($limit) possible units."</text>
   </message>
   <message name="nr_stat_header" section="nr">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Statistik für $region($region):"</text>
-    <text locale="en">"Statistics for $region($region):"</text>
   </message>
   <message name="nr_stat_maxentertainment" section="nr">
     <type>
       <arg name="max" type="int"/>
     </type>
-    <text locale="de">"Unterhaltung: max. $int($max) Silber"</text>
-    <text locale="en">"entertainment: max. $int($max) silver"</text>
   </message>
   <message name="nr_stat_morale" section="nr">
     <type>
       <arg name="morale" type="int"/>
     </type>
-    <text locale="de">"Moral der Bauern: $int($morale)"</text>
-    <text locale="en">"peasant morale: $int($morale)"</text>
   </message>
   <message name="nr_stat_luxuries" section="nr">
     <type>
       <arg name="max" type="int"/>
     </type>
-    <text locale="de">"Luxusgüter zum angegebenen Preis: $int($max)"</text>
-    <text locale="en">"luxury goods at this price: $int($max)"</text>
   </message>
   <message name="nr_stat_salary" section="nr">
     <type>
       <arg name="max" type="int"/>
     </type>
-    <text locale="de">"Lohn für Arbeit: $int($max) Silber"</text>
-    <text locale="en">"worker salary: $int($max) silver"</text>
   </message>
   <message name="nr_stat_salary_new" section="nr">
     <type>
       <arg name="max" type="int"/>
     </type>
-    <text locale="de">"Bauerneinnahmen: $int($max) Silber"</text>
-    <text locale="en">"peasant wages: $int($max) silver"</text>
   </message>
   <message name="nr_stat_people" section="nr">
     <type>
       <arg name="max" type="int"/>
     </type>
-    <text locale="de">"Personen: $int($max)"</text>
-    <text locale="en">"people: $int($max)"</text>
   </message>
   <message name="nr_stat_recruits" section="nr">
     <type>
       <arg name="max" type="int"/>
     </type>
-    <text locale="de">"Rekruten: max. $int($max) Bauern"</text>
-    <text locale="en">"recruits: $int($max) peasants"</text>
   </message>
   <message name="nr_score" section="nr">
     <type>
       <arg name="score" type="string"/>
       <arg name="average" type="string"/>
     </type>
-    <text locale="de">"Deine Partei hat ${score} Punkte. Der Durchschnitt für Parteien ähnlichen Alters ist ${average} Punkte."</text>
-    <text locale="en">"Your faction has a score of ${score}. The average score for similar factions is ${average}."</text>
   </message>
   <message name="nr_header_date" section="nr">
     <type>
       <arg name="game" type="string"/>
       <arg name="date" type="string"/>
     </type>
-    <text locale="de">"Report für $game, $date"</text>
-    <text locale="en">"Report for $game, $date"</text>
   </message>
   <message name="nr_vicinitystart" section="nr">
     <type>
       <arg name="dir" type="int"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Im $direction($dir) der Region liegt $trailto($region)"</text>
-    <text locale="en">"To the $direction($dir) lies $trailto($region)"</text>
   </message>
   <message name="nr_market_price" section="nr">
     <type>
       <arg name="price" type="int"/>
       <arg name="product" type="resource"/>
     </type>
-    <text locale="de">"$resource($product,0) $int($price) Silber"</text>
-    <text locale="en">"$resource($product,0) for $int($price) silver"</text>
   </message>
   <message name="nr_market_sale" section="nr">
     <type>
       <arg name="price" type="int"/>
       <arg name="product" type="resource"/>
     </type>
-    <text locale="de">"Auf dem Markt wird für $resource($product,0) $int($price) Silber verlangt."</text>
-    <text locale="en">"The local market offers $resource($product,0) at a price of $int($price) silver."</text>
   </message>
   <message name="nr_market_info_p" section="nr">
     <type>
       <arg name="p1" type="resource"/>
       <arg name="p2" type="resource"/>
     </type>
-    <text locale="de">"Auf dem Markt werden $resource($p1,0) und $resource($p2,0) feilgeboten."</text>
-    <text locale="en">"The local market offers $resource($p1,0) and $resource($p2,0)."</text>
   </message>
   <message name="nr_market_info_s" section="nr">
     <type>
       <arg name="p1" type="resource"/>
     </type>
-    <text locale="de">"Auf dem Markt wird $resource($p1,0) feilgeboten."</text>
-    <text locale="en">"The local market offers $resource($p1,0)."</text>
   </message>
   <message name="nr_potion_effect" section="nr">
     <type>
       <arg name="potion" type="resource"/>
       <arg name="left" type="int"/>
     </type>
-    <text locale="de">"Auf der Einheit $if($eq($left,1),"liegt","liegen") $int($left) Wirkung$if($eq($left,1),"","en") $resource($potion,1)."</text>
-    <text locale="en">"There $if($eq($left,1),"is","are") $int($left) $if($eq($left,1),"use","uses") of $resource($potion,1) left."</text>
   </message>
   <message name="nr_region_owner" section="nr">
     <type>
       <arg name="faction" type="faction"/>
     </type>
-    <text locale="de">"Die Region ist im Besitz von $faction($faction)."</text>
-    <text locale="en">"The region is owned by $faction($faction)."</text>
   </message>
   <message name="nr_borderlist_postfix" section="nr">
     <type>
       <arg name="transparent" type="int"/>
       <arg name="object" type="string"/>
     </type>
-    <text locale="de">"$if($transparent," befindet sich"," versperrt") ${object}$if($transparent,""," die Sicht")."</text>
-    <text locale="en">"$if($transparent," there is"," sight is blocked by ") ${object}."</text>
   </message>
   <message name="nr_building_besieged" section="nr">
     <type>
       <arg name="soldiers" type="int"/>
       <arg name="diff" type="int"/>
     </type>
-    <text locale="de">", belagert von $int($soldiers) Personen$if($lt($diff,0),""," (abgeschnitten)")"</text>
-    <text locale="en">", besieged by $int($soldiers) soldiers$if($lt($diff,0),""," (cut off)")"</text>
   </message>
 
   <message name="newbie_password" section="events">
     <type>
       <arg name="password" type="string"/>
     </type>
-    <text locale="de">"Dein Passwort lautet ${password}."</text>
-    <text locale="en">"Your password is ${password}."</text>
   </message>
   <message name="godcurse_destroy_ship" section="events">
     <type>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"Die Mannschaft krank vom vergifteten Wasser, Planken, Ruder und Segel zerfressen von den Wassern des verfluchten Meeres, ergibt sich die $ship($ship) in ihr Schicksal und sinkt."</text>
-    <text locale="en">"Her sailors sick from the poisened ocean, planks, rudder und sails corroded by the waters of the cursed ocean, the $ship($ship) finally succumbs to her destiny and sinks."</text>
   </message>
   <message name="skillpotion_use" section="events">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) benutzt einen Talenttrunk und fühlt, wie sein Wissen zunimmt."</text>
-    <text locale="en">"$unit($unit) uses a potion of skills and feels his knowledge grow."</text>
   </message>
   <message name="manacrystal_use" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="aura" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) benutzt einen Astralkristall und gewinnt $int($aura) Aura hinzu."</text>
-    <text locale="en">"$unit($unit) uses an astral crystal and gains $int($aura) aura."</text>
   </message>
   <message name="luxury_notsold" section="production">
     <type>
@@ -1008,8 +738,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieses Luxusgut wird hier nicht verkauft."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - These goods are not on sale here."</text>
   </message>
   <message name="resource_missing" section="production">
     <type>
@@ -1018,8 +746,6 @@
       <arg name="command" type="order"/>
       <arg name="missing" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dazu benötigt man $resource($missing,0)."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This requires $resource($missing,0)."</text>
   </message>
   <message name="race_notake" section="production">
     <type>
@@ -1028,8 +754,6 @@
       <arg name="command" type="order"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) nehmen nichts an."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) will not accept anything."</text>
   </message>
   <message name="race_noregroup" section="production">
     <type>
@@ -1038,8 +762,6 @@
       <arg name="command" type="order"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) können nicht neu gruppiert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) cannot be regrouped."</text>
   </message>
   <message name="race_nosteal" section="production">
     <type>
@@ -1048,8 +770,6 @@
       <arg name="command" type="order"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) können nichts stehelen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) cannot steal anything."</text>
   </message>
   <message name="regionmessage" section="mail">
     <type>
@@ -1057,8 +777,6 @@
       <arg name="region" type="region"/>
       <arg name="string" type="string"/>
     </type>
-    <text locale="de">"Eine Botschaft von $unit.dative($sender) aus $region($region): '$string'"</text>
-    <text locale="en">"A message by $unit($sender) from $region($region): '$string'"</text>
   </message>
   <message name="unitmessage" section="mail">
     <type>
@@ -1067,8 +785,6 @@
       <arg name="string" type="string"/>
       <arg name="sender" type="unit"/>
     </type>
-    <text locale="de">"In $region($region) erhielt $unit($unit) eine Botschaft von $unit.dative($sender): '$string'"</text>
-    <text locale="en">"In $region($region), $unit($unit) received a message by $unit($sender): '$string'"</text>
   </message>
   <message name="museumgiveback" section="mail">
     <type>
@@ -1077,22 +793,16 @@
       <arg name="items" type="items"/>
       <arg name="sender" type="unit"/>
     </type>
-    <text locale="de">"In $region($region) erhielt $unit($unit) von $unit.dative($sender) $resources($items)"</text>
-    <text locale="en">"In $region($region), $unit($unit) received $resources($items) from $unit($sender)"</text>
   </message>
   <message name="maintenance_nowork" section="events">
     <type>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$building($building) hat diese Woche nicht funktioniert, da zu Beginn der Woche der Unterhalt nicht gezahlt werden konnte."</text>
-    <text locale="en">"$building($building) was nonfunctional because upkeep could not be paid at the beginning of the week."</text>
   </message>
   <message name="icastle_dissolve" section="events">
     <type>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"Plötzlich löst sich $building($building) in kleine Traumwolken auf."</text>
-    <text locale="en">"$building($building) suddenly dissolves into small pink clouds."</text>
   </message>
   <message name="buildingcrash" section="events">
     <type>
@@ -1101,8 +811,6 @@
       <arg name="opfer" type="int"/>
       <arg name="road" type="int"/>
     </type>
-    <text locale="de">"In $region($region) stürzte $building($building) ein.$if($road," Beim Einsturz wurde die halbe Straße vernichtet.","")$if($opfer," $int($opfer) Opfer $if($eq($opfer,1),"ist","sind") zu beklagen.","")"</text>
-    <text locale="en">"$building($building) in $region($region) collapses.$if($road," The collapse ruined half of the road.","")$if($opfer," There are $int($opfer) casualties.","")"</text>
   </message>
 
   <message name="error_pflnorecruit" section="errors">
@@ -1111,8 +819,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - In der Ebene der Herausforderung kann niemand rekrutiert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot recruit in this plane."</text>
   </message>
 
   <message name="error_lowstealth" section="errors">
@@ -1121,8 +827,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann sich nicht so gut tarnen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' -The unit cannot hide that well."</text>
   </message>
 
   <message name="destroy_ship_0" section="events">
@@ -1130,8 +834,6 @@
       <arg name="unit" type="unit"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="en">"$ship($ship) was destroyed by $unit($unit)."</text>
-    <text locale="de">"$ship($ship) wurde von $unit($unit) zerstört."</text>
   </message>
 
   <message name="destroy_ship_1" section="events">
@@ -1139,8 +841,6 @@
       <arg name="unit" type="unit"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="en">"$unit($unit) could not destroy $ship($ship)."</text>
-    <text locale="de">"$unit($unit) konnte $ship($ship) nicht zerstören."</text>
   </message>
 
   <message name="destroy_ship_2" section="events">
@@ -1148,24 +848,18 @@
       <arg name="unit" type="unit"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="en">"$unit($unit) was detected while trying to destroy $ship($ship)."</text>
-    <text locale="de">"$unit($unit) wurde beim Versuch $ship($ship) zu zerstören entdeckt."</text>
   </message>
 
   <message name="destroy_ship_3" section="events">
     <type>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="en">"Somebody attempted to destroy $ship($ship)."</text>
-    <text locale="de">"Es wurde versucht, $ship($ship) zu zerstören."</text>
   </message>
 
   <message name="destroy_ship_4" section="events">
     <type>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="en">"$ship($ship) was destroyed."</text>
-    <text locale="de">"$ship($ship) wurde zerstört."</text>
   </message>
 
   <message name="sink_lost_msg" section="events">
@@ -1174,8 +868,6 @@
       <arg name="region" type="region"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$int($amount) Personen von $unit($unit) ertrinken.$if($isnull($region),""," Die Einheit rettet sich nach $region($region).")"</text>
-    <text locale="en">"$int($amount) people of $unit($unit) drown.$if($isnull($region),""," The unit makes it to $region($region).")"</text>
   </message>
 
   <message name="sink_saved_msg" section="events">
@@ -1183,8 +875,6 @@
       <arg name="region" type="region"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) überlebt unbeschadet und rettet sich nach $region($region)."</text>
-    <text locale="en">"$unit($unit) survives unscathed and makes it to $region($region)."</text>
   </message>
 
   <message name="sink_msg" section="events">
@@ -1192,8 +882,6 @@
       <arg name="ship" type="ship"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$ship($ship) versinkt in den Fluten von $region($region)."</text>
-    <text locale="en">"$ship($ship) disappears in the depths of $region($region)."</text>
   </message>
 
   <message name="enemy_discovers_spy_msg" section="events">
@@ -1201,8 +889,6 @@
       <arg name="ship" type="ship"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) wurde beim versenken von $ship($ship) entdeckt."</text>
-    <text locale="en">"$unit($unit) was spotted sinking $ship($ship)."</text>
   </message>
 
   <message name="spy_discovered_msg" section="events">
@@ -1211,8 +897,6 @@
       <arg name="unit" type="unit"/>
       <arg name="saboteur" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) entdeckte $unit($saboteur) beim Versenken von $ship($ship)."</text>
-    <text locale="en">"$unit($unit) caught $unit($saboteur) trying to sink $ship($ship)."</text>
   </message>
 
   <message name="drown" section="events">
@@ -1220,8 +904,6 @@
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) ertrinkt in $region($region)."</text>
-    <text locale="en">"$unit($unit) drowns in $region($region)."</text>
   </message>
 
   <message name="poison_damage" section="events">
@@ -1229,8 +911,6 @@
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) nimmt Schaden durch den Giftelementar in $region($region)."</text>
-    <text locale="en">"$unit($unit) is taking poison damage in $region($region)."</text>
   </message>
 
   <message name="poison_death" section="events">
@@ -1238,8 +918,6 @@
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) stirbt am Schaden durch den Giftelementar in $region($region)."</text>
-    <text locale="en">"$unit($unit) dies from poison damage taken in $region($region)."</text>
   </message>
 
   <message name="find_manual" section="events">
@@ -1248,8 +926,6 @@
       <arg name="location" type="string"/>
       <arg name="book" type="string"/>
     </type>
-    <text locale="de">"$unit($unit) stolpert bei der Erforschung der Region über $localize($location). Nähere Durchsuchung fördert ein zerfleddertes altes Buch mit dem Titel '$localize($book)' zu Tage. Der Wissensschub ist enorm."</text>
-    <text locale="en">"$unit($unit) stumbles upon $localize($location) while exploring the region. Closer inspection reveals a torn old book titled '$localize($book)'. The expansion of knowledge is tremendous."</text>
   </message>
 
   <message name="curseinfo::auraboost_0" section="events">
@@ -1257,8 +933,6 @@
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) fühlt sich von starken magischen Energien durchströmt. ($int36($id))"</text>
-    <text locale="en">"Powerful magical energies are pulsing through $unit($unit). ($int36($id))"</text>
   </message>
 
   <message name="curseinfo::auraboost_1" section="events">
@@ -1266,8 +940,6 @@
       <arg name="unit" type="unit"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) hat Schwierigkeiten seine magischen Energien zu sammeln. ($int36($id))"</text>
-    <text locale="en">"$unit($unit) finds it difficult to gather its magical energies. ($int36($id))"</text>
   </message>
 
   <message name="cast_stun_effect" section="magic">
@@ -1276,8 +948,6 @@
       <arg name="spell" type="spell"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell): $int($amount) Krieger sind für einen Moment benommen."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell): $int($amount) fighters were momentarily stunned."</text>
   </message>
 
   <message name="cast_rally_effect" section="magic">
@@ -1285,8 +955,6 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) besänftigt den Bauernaufstand in $region($region)."</text>
-    <text locale="en">"$unit($mage) quells the uprising in $region($region)."</text>
   </message>
 
   <message name="cast_auraleak_effect" section="magic">
@@ -1294,8 +962,6 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) rief in $region($region) einen Riss in dem Gefüge der Magie hervor, der alle magische Kraft aus der Region riss."</text>
-    <text locale="en">"$unit($mage) in $region($region) caused a tear in the fabric of magic, that sucked all magical energies out of the region."</text>
   </message>
 
   <message name="cast_sleep_effect" section="magic">
@@ -1304,8 +970,6 @@
       <arg name="spell" type="spell"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell): $int($amount) Krieger wurden in Schlaf versetzt."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell): $int($amount) fighters have fallen asleep."</text>
   </message>
 
   <message name="cast_drainlife_effect" section="magic">
@@ -1314,8 +978,6 @@
       <arg name="spell" type="spell"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell): $int($amount) Kriegern wurde ihre Lebenskraft entzogen."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell): $int($amount) fighters had their life energy drained."</text>
   </message>
 
   <message name="cast_petrify_effect" section="magic">
@@ -1324,8 +986,6 @@
       <arg name="spell" type="spell"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell): $int($amount) Kriegern wurden versteinert."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell): $int($amount) fighters were petrified."</text>
   </message>
 
   <message name="cast_berserk_effect" section="magic">
@@ -1334,8 +994,6 @@
       <arg name="spell" type="spell"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell): $int($amount) Krieger wurden in einen Blutrausch versetzt."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell): $int($amount) fighters went into a mindless rage."</text>
   </message>
 
   <message name="cast_frighten_effect" section="magic">
@@ -1344,8 +1002,6 @@
       <arg name="spell" type="spell"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell): $int($amount) Krieger wurden eingeschüchtert."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell): $int($amount) fighters were intimidated."</text>
   </message>
 
   <message name="sp_flee_effect_0" section="magic">
@@ -1353,8 +1009,6 @@
       <arg name="mage" type="unit"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell), aber es gab niemanden, der beeinflusst werden konnte."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell), but nobody is affected."</text>
   </message>
 
   <message name="sp_flee_effect_1" section="magic">
@@ -1363,8 +1017,6 @@
       <arg name="spell" type="spell"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell): $int($amount) Krieger wurden von Furcht gepackt."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell): $int($amount) fighters were consumed by fear."</text>
   </message>
 
   <message name="cast_escape_effect" section="magic">
@@ -1372,8 +1024,6 @@
       <arg name="mage" type="unit"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell): Das Kampfgetümmel erstirbt und er kann unbehelligt seines Weges ziehen."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell): The noise of the battle dies down and the mage is able to slip away unharmed."</text>
   </message>
 
   <message name="cast_storm_effect" section="magic">
@@ -1381,8 +1031,6 @@
       <arg name="mage" type="unit"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell): Ein Sturm kommt auf und die Schützen können kaum noch zielen."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell): Strong stormwinds are blowing and the archers are having a hard time aiming."</text>
   </message>
 
   <message name="cast_tired_effect" section="magic">
@@ -1391,8 +1039,6 @@
       <arg name="spell" type="spell"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell): $int($amount) Krieger schleppten sich müde in den Kampf."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell): $int($amount) fighters had trouble staying awake."</text>
   </message>
 
   <message name="cast_hero_effect" section="magic">
@@ -1401,8 +1047,6 @@
       <arg name="spell" type="spell"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell): $int($amount) Krieger wurden moralisch gestärkt."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell): $int($amount) fighters had their moral boosted."</text>
   </message>
 
   <message name="cast_speed_effect" section="magic">
@@ -1411,32 +1055,24 @@
       <arg name="spell" type="spell"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell): $int($amount) Krieger wurden magisch beschleunigt."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell): $int($amount) fighters were magically accelerated."</text>
   </message>
 
   <message name="rust_effect_0" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) ruft ein fürchterliches Unwetter über seine Feinde, doch es gab niemanden mehr, den dies treffen konnte."</text>
-    <text locale="en">"$unit($mage) calls forth a terrible torment over the enemy side, but there was nobody who could be affected by it."</text>
   </message>
 
   <message name="rust_effect_1" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) ruft ein fürchterliches Unwetter über seine Feinde, doch der magische Regen zeigt keinen Effekt."</text>
-    <text locale="en">"$unit($mage) causes a terrible storm over the enemy, but the magic rain does not do any harm."</text>
   </message>
 
   <message name="rust_effect_2" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) ruft ein fürchterliches Unwetter über seine Feinde. Der magischen Regen lässt alles Eisen rosten."</text>
-    <text locale="en">"$unit($mage) calls forth a terrible torment over the enemy. The magical rain makes all iron rusty."</text>
   </message>
 
   <message name="healing_effect_0" section="magic">
@@ -1444,8 +1080,6 @@
       <arg name="mage" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) kümmert sich um die Verletzten und heilt $int($amount) Verwundete."</text>
-    <text locale="en">"$unit($mage) sees after the wounded and heals $int($amount)."</text>
   </message>
 
   <message name="healing_effect_1" section="magic">
@@ -1454,8 +1088,6 @@
       <arg name="amount" type="int"/>
       <arg name="item" type="resource"/>
     </type>
-    <text locale="de">"$unit($mage) kümmert sich um die Verletzten und benutzt ein $resource($item,1), um den Zauber zu verstärken. $int($amount) Verwundete werden geheilt."</text>
-    <text locale="en">"$unit($mage) sees after the wounded and heals $int($amount). A $resource($item,1) improves the spell."</text>
   </message>
 
   <message name="sp_eternizewall_effect" section="magic">
@@ -1464,8 +1096,6 @@
       <arg name="building" type="building"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Mit einem Ritual bindet $unit($mage) die magischen Kräfte der Erde von $region($region) in die Mauern von $building($building)."</text>
-    <text locale="en">"$unit($mage) performs a ritual that binds the magical forces of $region($region) into the walls of $building($building)."</text>
   </message>
 
   <message name="sp_permtransfer_effect" section="magic">
@@ -1474,8 +1104,6 @@
       <arg name="target" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) opfert $unit($target) $int($amount) Aura."</text>
-    <text locale="en">"$unit($mage) sacrifices $int($amount) aura for $unit($target)."</text>
   </message>
 
   <message name="reanimate_effect_0" section="magic">
@@ -1483,8 +1111,6 @@
       <arg name="mage" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) beginnt ein Ritual der Wiederbelebung. $int($amount) Krieger stehen von den Toten auf."</text>
-    <text locale="en">"$unit($mage) begins a ritual of resurrection. $int($amount) warriors rise from the dead."</text>
   </message>
 
   <message name="reanimate_effect_1" section="magic">
@@ -1493,21 +1119,15 @@
       <arg name="amount" type="int"/>
       <arg name="item" type="resource"/>
     </type>
-    <text locale="de">"$unit($mage) beginnt ein Ritual der Wiederbelebung und benutzt ein $resource($item,1), um den Zauber zu verstärken. $int($amount) Krieger stehen von den Toten auf."</text>
-    <text locale="en">"$unit($mage) begins a ritual of resurrection augmented by a $resource($item,1). $int($amount) warriors rise from the dead."</text>
   </message>
 
   <message name="chaosgate_effect_1" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) öffnet ein Chaostor."</text>
-    <text locale="en">"$unit($mage) opens a chaos gate."</text>
   </message>
 
   <message name="chaosgate_effect_2" section="magic">
-    <text locale="de">"Ein Wirbel aus blendendem Licht erscheint."</text>
-    <text locale="en">"A vortex of blinding light appears."</text>
   </message>
 
   <message name="summonundead_effect_0" section="magic">
@@ -1515,8 +1135,6 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) kann in $region($region) keine Untoten rufen."</text>
-    <text locale="en">"$unit($mage) cannot summon any undead in $region($region)."</text>
   </message>
 
   <message name="summonundead_effect_1" section="magic">
@@ -1525,8 +1143,6 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) erweckt in $region($region) $int($amount) Untote aus ihren Gräbern."</text>
-    <text locale="en">"$unit($mage) calls $int($amount) undead from their graves in $region($region)."</text>
   </message>
 
   <message name="summonundead_effect_2" section="magic">
@@ -1534,16 +1150,12 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) stört in $region($region) die Ruhe der Toten."</text>
-    <text locale="en">"$unit($mage) communicates with the dead in $region($region)."</text>
   </message>
 
   <message name="viewreality_effect" section="magic">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) gelingt es, durch die Nebel auf die Realität zu blicken."</text>
-    <text locale="en">"$unit($unit) manages to catch a glimpse of reality through the fog."</text>
   </message>
 
   <message name="recruit_effect" section="magic">
@@ -1551,8 +1163,6 @@
       <arg name="mage" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) konnte $int($amount) $if($eq($amount,1),"Bauer","Bauern") anwerben."</text>
-    <text locale="en">"$unit($mage) managed to recruit $int($amount) $if($eq($amount,1),"peasant","peasants")."</text>
   </message>
 
   <message name="error_giveeye" section="events">
@@ -1561,67 +1171,49 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Eine höhere Macht hindert $unit($unit) daran, das Objekt zu übergeben. 'ES IST DEINS, MEIN KIND. DEINS GANZ ALLEIN'."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - A higher power prevents $unit($unit) from giving the object away. 'IT IS YOURS MY CHILD. ONLY YOURS.'."</text>
   </message>
 
   <message name="iceberg_melt" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Der Eisberg $region($region) schmilzt."</text>
-    <text locale="en">"The iceberg $region($region) melts."</text>
   </message>
   <message name="iceberg_create" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Der Gletscher von $region($region) bricht und treibt davon."</text>
-    <text locale="en">"The glacier in $region($region) breaks up and drifts away."</text>
   </message>
   <message name="iceberg_land" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Der Eisberg $region($region) treibt an eine Küste."</text>
-    <text locale="en">"The iceberg $region($region) drifts onto a coast."</text>
   </message>
   <message name="overrun_by_iceberg_des" section="events">
     <type>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"Die $ship($ship) wird bei einer Kollision mit einem Eisberg zerstört."</text>
-    <text locale="en">"The $ship($ship) has been destroyed by a collision with an iceberg."</text>
   </message>
   <message name="overrun_by_iceberg" section="events">
     <type>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"Die $ship($ship) wird bei einer Kollision mit einem Eisberg beschädigt."</text>
-    <text locale="en">"The $ship($ship) has been damaged by a collision with an iceberg."</text>
   </message>
   <message name="massive_overload" section="events">
     <type>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"Die $ship($ship) ist zu stark überladen und wird stark beschädigt."</text>
-    <text locale="en">"The $ship($ship) is massively overloaded and is damaged heavily."</text>
   </message>
   <message name="ship_drift" section="events">
     <type>
       <arg name="ship" type="ship"/>
       <arg name="dir" type="direction"/>
     </type>
-    <text locale="de">"Die $ship($ship) treibt nach $direction($dir)."</text>
-    <text locale="en">"The ship $ship($ship) drifts to the $direction($dir)."</text>
   </message>
   <message name="iceberg_drift" section="events">
     <type>
       <arg name="region" type="region"/>
       <arg name="dir" type="direction"/>
     </type>
-    <text locale="de">"Der Eisberg $region($region) treibt nach $direction($dir)."</text>
-    <text locale="en">"The iceberg $region($region) drifts $direction($dir)."</text>
   </message>
   <message name="casualties" section="battle">
     <type>
@@ -1631,8 +1223,6 @@
       <arg name="run" type="int"/>
       <arg name="runto" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) verlor $int($fallen) Personen$if($alive,", $int($alive) überlebten","")$if($run," und $int($run) flohen$if($isnull($runto),""," nach $region($runto)")","")."</text>
-    <text locale="en">"$unit($unit) lost $int($fallen) people$if($alive,", $int($alive) survived","")$if($run," and $int($run) fled$if($isnull($runto),""," to $region($runto)")","")."</text>
   </message>
   <message name="killsandhits" section="battle">
     <type>
@@ -1640,31 +1230,23 @@
       <arg name="hits" type="int"/>
       <arg name="kills" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) erzielte $int($hits) Treffer und tötete $int($kills) Gegner."</text>
-    <text locale="en">"$unit($unit) hit $int($hits) times and killed $int($kills) enemies."</text>
   </message>
   <message name="battle_msg" section="battle">
     <type>
       <arg name="string" type="string"/>
     </type>
-    <text locale="de">"$string"</text>
-    <text locale="en">"$string"</text>
   </message>
   <message name="para_army_index" section="battle">
     <type>
       <arg name="index" type="int"/>
       <arg name="name" type="string"/>
     </type>
-    <text locale="de">"Heer $int($index): $name"</text>
-    <text locale="en">"Army $int($index): $name"</text>
   </message>
 
   <message name="sp_icastle_effect" section="magic">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Verwundert blicken die Bauern von $region($region) auf ein neues Gebäude."</text>
-    <text locale="en">"Flabbergasted, the peasants of $region($region) behold a new building."</text>
   </message>
 
   <message name="sp_bloodsacrifice_effect" section="magic">
@@ -1674,8 +1256,6 @@
       <arg name="command" type="order"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) gewinnt durch das Ritual $int($amount) Aura."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) receives $int($amount) aura."</text>
   </message>
 
   <message name="sp_holyground_effect" section="magic">
@@ -1683,8 +1263,6 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) beschwört Naturgeister in den Boden von $region($region)."</text>
-    <text locale="en">"$unit($mage) summons natural spirits into the ground of $region($region)."</text>
   </message>
   <message name="unholypower_limitedeffect" section="magic">
     <type>
@@ -1693,8 +1271,6 @@
       <arg name="race" type="race"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) verwandelt $int($amount) aus $unit($target) in $race($race,0)."</text>
-    <text locale="en">"$unit($mage) transforms $int($amount) from $unit($target) into $race($race,0)."</text>
   </message>
   <message name="unholypower_effect" section="magic">
     <type>
@@ -1702,38 +1278,28 @@
       <arg name="target" type="unit"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($mage) verwandelt $unit($target) in $race($race,0)."</text>
-    <text locale="en">"$unit($mage) tranforms $unit($target) to $race($race,0)."</text>
   </message>
   <message name="puttorest" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) erlöst die gequälten Seelen der Toten."</text>
-    <text locale="en">"$unit($mage) redeems the tormented souls of the dead."</text>
   </message>
   <message name="becomewyrm" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) verwandelt sich in einen Wyrm."</text>
-    <text locale="en">"$unit($mage) turns into a wyrm."</text>
   </message>
   <message name="firewall_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) erschafft in $region($region) eine Wand aus Feuer."</text>
-    <text locale="en">"$unit($mage) creates a wall of fire in $region($region)."</text>
   </message>
   <message name="sp_raisepeasantmob_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) wiegelt in $region($region) die Bauern zum Aufstand auf."</text>
-    <text locale="en">"$unit($mage) incites a revolt among the peasants of $region($region)."</text>
   </message>
 
   <message name="sp_raisepeasants_effect" section="magic">
@@ -1742,8 +1308,6 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) wiegelt in $region($region) $int($amount) Bauern zum Aufstand auf."</text>
-    <text locale="en">"$unit($mage) incites a revolt among $int($amount) peasants of $region($region)."</text>
   </message>
 
   <message name="sp_depression_effect" section="magic">
@@ -1751,8 +1315,6 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) sorgt in $region($region) für Trübsal unter den Bauern."</text>
-    <text locale="en">"$unit($mage) causes great sadness among the peasants of $region($region)."</text>
   </message>
 
   <message name="icastle_create" section="magic">
@@ -1761,8 +1323,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Magier erschafft ein Traumgebäude."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The magician creates an illusionary building."</text>
   </message>
   <message name="sp_shapeshift_fail" section="errors">
     <type>
@@ -1772,8 +1332,6 @@
       <arg name="target" type="unit"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($target) kann nicht $race($race,1) werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($target) cannot take the form of $race($race,1)."</text>
   </message>
 
   <message name="sp_movecastle_fail_0" section="magic">
@@ -1782,8 +1340,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Elementar ist zu klein, um das Gebäude zu tragen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The elemental is too small to carry the building."</text>
   </message>
 
   <message name="sp_movecastle_fail_1" section="magic">
@@ -1793,8 +1349,6 @@
       <arg name="command" type="order"/>
       <arg name="direction" type="direction"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Elementar weigert sich, nach $direction($direction) zu gehen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The elemental refuses to go $direction($direction)."</text>
   </message>
 
   <message name="sp_migranten_fail1" section="magic">
@@ -1804,8 +1358,6 @@
       <arg name="command" type="order"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($target) ist von unserer Art, das Ritual wäre verschwendete Aura."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($target) is one of our kind, we should not waste aura on this."</text>
   </message>
   <message name="sp_migranten" section="magic">
     <type>
@@ -1814,8 +1366,6 @@
       <arg name="command" type="order"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($target) wird von uns aufgenommen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($target) has become one of our kind."</text>
   </message>
   <message name="summondragon" section="magic">
     <type>
@@ -1824,8 +1374,6 @@
       <arg name="command" type="order"/>
       <arg name="target" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) ruft Drachen nach $region($target)."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) calls dragons to $region($target)."</text>
   </message>
 
   <message name="magiccreate_effect" section="magic">
@@ -1836,8 +1384,6 @@
       <arg name="amount" type="int"/>
       <arg name="object" type="string"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) erschafft $int($amount) ${object}."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) creates $int($amount) ${object}."</text>
   </message>
 
   <message name="sp_movecastle_effect" section="magic">
@@ -1845,8 +1391,6 @@
       <arg name="building" type="building"/>
       <arg name="direction" type="direction"/>
     </type>
-    <text locale="de">"Ein Beben erschüttert $building($building). Viele kleine Pseudopodien erheben das Gebäude und tragen es in Richtung $direction($direction)."</text>
-    <text locale="en">"An tremor shakes $building($building). Many little pseudopods lift up the building and carry it to $direction($direction)."</text>
   </message>
 
   <message name="use_tacticcrystal" section="magic">
@@ -1854,15 +1398,11 @@
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) benutzt in $region($region) ein Traumauge."</text>
-    <text locale="en">"$unit($unit) uses a dreameye in $region($region)."</text>
   </message>
   <message name="use_antimagiccrystal" section="magic">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) benutzt einen Antimagiekristall."</text>
-    <text locale="en">"$unit($unit) uses an antimagic crystal."</text>
   </message>
   <message name="magicboost_effect" section="magic">
     <type>
@@ -1870,8 +1410,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Sphären des Chaos geben dem Magier einen Teil ihrer Kraft."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The Spheres of Chaos return a part of his power to the magician."</text>
   </message>
   <message name="destroy_magic_noeffect" section="magic">
     <type>
@@ -1879,8 +1417,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Magier konnte keinen Fluch zerstören."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The magician could not destroy any curse."</text>
   </message>
   <message name="speed_time_effect" section="magic">
     <type>
@@ -1888,8 +1424,6 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"In $region($region) dehnt $unit($unit) die Zeit für $int($amount) Personen."</text>
-    <text locale="en">"In $region($region), $unit($unit) bends time for $int($amount) men."</text>
   </message>
   <message name="destroy_magic_effect" section="magic">
     <type>
@@ -1899,8 +1433,6 @@
       <arg name="succ" type="int"/>
       <arg name="target" type="string"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Magier zerstört $int($succ) Flüche auf ${target}."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The magician destroys $int($succ) spells on ${target}."</text>
   </message>
   <message name="destroy_curse_effect" section="magic">
     <type>
@@ -1910,8 +1442,6 @@
       <arg name="id" type="string"/>
       <arg name="target" type="string"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Magier zerstört den Fluch ($id) auf ${target}."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The magician destroys the spell ($id) on ${target}."</text>
   </message>
   <message name="destroy_curse_noeffect" section="magic">
     <type>
@@ -1921,16 +1451,12 @@
       <arg name="id" type="string"/>
       <arg name="target" type="string"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Zauber ist nicht stark genug, um den Fluch ($id) auf ${target} zu zerstören."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The spell is not strong enough to destroy the curse ($id) on ${target}."</text>
   </message>
   <message name="deathcloud_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) beschwört einen Giftelementar in $region($region)."</text>
-    <text locale="en">"$unit($mage) summons a poison elemental in $region($region)."</text>
   </message>
 
   <message name="fumblecurse" section="magic">
@@ -1938,8 +1464,6 @@
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) wird von einem Unbekannten verflucht."</text>
-    <text locale="en">"$unit($unit) in $region($region) was cursed by an unknown magician."</text>
   </message>
 
   <message name="sparkle_effect" section="magic">
@@ -1947,24 +1471,18 @@
       <arg name="mage" type="unit"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) belegt $unit($target) mit einem Zauber."</text>
-    <text locale="en">"$unit($mage) puts a spell on $unit($target)."</text>
   </message>
   <message name="heat_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) belegt $unit($target) mit einem Kälteschutz."</text>
-    <text locale="en">"$unit($mage) puts protection from cold on $unit($target)."</text>
   </message>
   <message name="rust_fail" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) legt einen Rosthauch auf $unit($target), doch der Rosthauch fand keine Nahrung."</text>
-    <text locale="en">"$unit($mage) puts a spell of rust on $unit($target) but it found nothing to consume."</text>
   </message>
   <message name="rust_effect" section="magic">
     <type>
@@ -1972,61 +1490,45 @@
       <arg name="target" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) legt einen Rosthauch auf $unit($target). $int($amount) Waffen wurden vom Rost zerfressen."</text>
-    <text locale="en">"$unit($mage) puts a spell of rust on $unit($target). $int($amount) weapons are eaten by rust."</text>
   </message>
   <message name="growtree_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">$if($isnull($mage),"Ein unentdeckter Magier",$unit($mage)) erschuf einen heiligen Hain von $int($amount) Schößlingen.</text>
-    <text locale="en">$if($isnull($mage),"An unknown magician",$unit($mage)) created a holy forest of $int($amount) young trees.</text>
   </message>
   <message name="raindance_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$if($isnull($mage),"Ein unentdeckter Magier",$unit($mage)) führt einen sonderbaren Tanz auf. Kurz darauf beginnt es zu regnen."</text>
-    <text locale="en">"$if($isnull($mage),"an unseen magician",$unit($mage)) dances a strange dance. Shortly after, rain begins to fall on the fields."</text>
   </message>
   <message name="harvest_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$if($isnull($mage),"Ein unentdeckter Magier",$unit($mage)) segnet in einem kurzen Ritual die Felder."</text>
-    <text locale="en">"$if($isnull($mage),"An unseen magician",$unit($mage)) blesses the fields in a short ritual."</text>
   </message>
   <message name="maelstrom_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) beschwört die Mächte des Wassers und ein gigantischer Strudel bildet sich."</text>
-    <text locale="en">"$unit($mage) summons the power of the seas and a giant maelstrom forms."</text>
   </message>
   <message name="ent_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) belebt $int($amount) Bäume."</text>
-    <text locale="en">"$unit($mage) animates $int($amount) trees."</text>
   </message>
   <message name="path_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) sorgt für trockene Straßen in $region($region)."</text>
-    <text locale="en">"$unit($mage) creates dry and well-repaired roads in $region($region)."</text>
   </message>
   <message name="wind_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"$unit($mage) erfleht den Segen der Götter des Windes und des Wassers für $ship($ship)."</text>
-    <text locale="en">"$unit($mage) asks the gods of wind and water on behalf of the $ship($ship)."</text>
   </message>
   <message name="auratransfer_success" section="magic">
     <type>
@@ -2034,8 +1536,6 @@
       <arg name="aura" type="int"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) transferiert $int($aura) Aura auf $unit($target)."</text>
-    <text locale="en">"$unit($unit) transfers $int($aura) aura to $unit($target)."</text>
   </message>
   <message name="stealaura_success" section="magic">
     <type>
@@ -2043,31 +1543,23 @@
       <arg name="target" type="unit"/>
       <arg name="aura" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) entzieht $unit($target) $int($aura) Aura."</text>
-    <text locale="en">"$unit($mage) draws $int($aura) aura from $unit($target)."</text>
   </message>
   <message name="stealaura_detect" section="magic">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="aura" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) fühlt seine magischen Kräfte schwinden und verliert $int($aura) Aura."</text>
-    <text locale="en">"$unit($unit) feels the powers of magic fade and loses $int($aura) aura."</text>
   </message>
   <message name="stealaura_fail_detect" section="magic">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) fühlt sich einen Moment seltsam geschwächt."</text>
-    <text locale="en">"$unit($unit) fühlt strangely weakened."</text>
   </message>
   <message name="stealaura_fail" section="magic">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) konnte $unit($target) keine Aura entziehen."</text>
-    <text locale="en">"$unit($unit) could not draw aura from $unit($target)."</text>
   </message>
   <message name="teleport_success" section="magic">
     <type>
@@ -2075,8 +1567,6 @@
       <arg name="source" type="region"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) wurde von $region($source) nach $unit($target) teleportiert."</text>
-    <text locale="en">"$unit($unit) was teleported from $region($source) to $unit($target)."</text>
   </message>
   <message name="analyse_ship_age" section="magic">
     <type>
@@ -2085,8 +1575,6 @@
       <arg name="curse" type="curse"/>
       <arg name="months" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) fand heraus, dass auf $ship($ship) der Zauber '$curse($curse)' liegt, der noch etwa $int($months) Wochen bestehen bleibt."</text>
-    <text locale="en">"$unit($mage) discovers that $ship($ship) is charmed with '$curse($curse)', which will last for, about $int($months) more weeks."</text>
   </message>
   <message name="analyse_building_age" section="magic">
     <type>
@@ -2095,8 +1583,6 @@
       <arg name="curse" type="curse"/>
       <arg name="months" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) fand heraus, dass auf $building($building) der Zauber '$curse($curse)' liegt, der noch etwa $int($months) Wochen bestehen bleibt."</text>
-    <text locale="en">"$unit($mage) discovers that $building($building) is charmed with '$curse($curse)', which will last for about $int($months) more weeks."</text>
   </message>
   <message name="analyse_unit_age" section="magic">
     <type>
@@ -2105,8 +1591,6 @@
       <arg name="curse" type="curse"/>
       <arg name="months" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) fand heraus, dass auf $unit($unit) der Zauber '$curse($curse)' liegt, der noch etwa $int($months) Wochen bestehen bleibt."</text>
-    <text locale="en">"$unit($mage) discovers that $unit($unit) is charmed with '$curse($curse)' that will last for about $int($months) more weeks."</text>
   </message>
   <message name="analyse_region_age" section="magic">
     <type>
@@ -2115,8 +1599,6 @@
       <arg name="curse" type="curse"/>
       <arg name="months" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) fand heraus, dass auf $region($region) der Zauber '$curse($curse)' liegt, der noch etwa $int($months) Wochen bestehen bleibt."</text>
-    <text locale="en">"$unit($mage) discovers that $region($region) is charmed with '$curse($curse)', which will last for about $int($months) more weeks."</text>
   </message>
   <message name="analyse_ship_noage" section="magic">
     <type>
@@ -2124,8 +1606,6 @@
       <arg name="ship" type="ship"/>
       <arg name="curse" type="curse"/>
     </type>
-    <text locale="de">"$unit($mage) fand heraus, dass auf $ship($ship) der Zauber '$curse($curse)' liegt, dessen Kraft ausreicht, um noch Jahrhunderte bestehen zu bleiben."</text>
-    <text locale="en">"$unit($mage) discovers that $ship($ship) is charmed with '$curse($curse)', which will last for centuries."</text>
   </message>
   <message name="analyse_building_noage" section="magic">
     <type>
@@ -2133,8 +1613,6 @@
       <arg name="building" type="building"/>
       <arg name="curse" type="curse"/>
     </type>
-    <text locale="de">"$unit($mage) fand heraus, dass auf $building($building) der Zauber '$curse($curse)' liegt, dessen Kraft ausreicht, um noch Jahrhunderte bestehen zu bleiben."</text>
-    <text locale="en">"$unit($mage) discovers that $building($building) is charmed with '$curse($curse)', which will last for centuries."</text>
   </message>
   <message name="analyse_unit_noage" section="magic">
     <type>
@@ -2142,8 +1620,6 @@
       <arg name="unit" type="unit"/>
       <arg name="curse" type="curse"/>
     </type>
-    <text locale="de">"$unit($mage) fand heraus, dass auf $unit($unit) der Zauber '$curse($curse)' liegt, dessen Kraft ausreicht, um noch Jahrhunderte bestehen zu bleiben."</text>
-    <text locale="en">"$unit($mage) discovers that $unit($unit) is charmed with '$curse($curse)', which will last for centuries."</text>
   </message>
   <message name="analyse_region_noage" section="magic">
     <type>
@@ -2151,72 +1627,54 @@
       <arg name="region" type="region"/>
       <arg name="curse" type="curse"/>
     </type>
-    <text locale="de">"$unit($mage) fand heraus, dass auf $region($region) der Zauber '$curse($curse)' liegt, dessen Kraft ausreicht, um noch Jahrhunderte bestehen zu bleiben."</text>
-    <text locale="en">"$unit($mage) discovers that $region($region) is charmed with '$curse($curse)', which will last for centuries."</text>
   </message>
   <message name="analyse_ship_fail" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"$unit($mage) meint, dass auf $ship($ship) ein Zauber liegt, konnte aber über den Zauber nichts herausfinden."</text>
-    <text locale="en">"It appears to $unit($mage) that $ship($ship) is charmed, but no details have been revealed."</text>
   </message>
   <message name="analyse_building_fail" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($mage) meint, dass auf $building($building) ein Zauber liegt, konnte aber über den Zauber nichts herausfinden."</text>
-    <text locale="en">"It appears to $unit($mage) that $building($building) is charmed, but no details have been revealed."</text>
   </message>
   <message name="analyse_unit_fail" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) meint, dass $unit($unit) verzaubert ist, konnte aber über den Zauber nichts herausfinden."</text>
-    <text locale="en">"It appears to $unit($mage) that $unit($unit) is charmed, but no details have been revealed."</text>
   </message>
   <message name="analyse_region_fail" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) meint, dass auf $region($region) ein Zauber liegt, konnte aber über den Zauber nichts herausfinden."</text>
-    <text locale="en">"It appears to $unit($mage) that $region($region) is charmed, but no details have been revealed."</text>
   </message>
   <message name="analyse_ship_nospell" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"$unit($mage) meint, dass auf $ship($ship) kein Zauber liegt."</text>
-    <text locale="en">"It appears to $unit($mage) that $ship($ship) is not charmed."</text>
   </message>
   <message name="analyse_building_nospell" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($mage) meint, dass auf $building($building) kein Zauber liegt."</text>
-    <text locale="en">"It appears to $unit($mage) that $building($building) is not charmed."</text>
   </message>
   <message name="analyse_unit_nospell" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) meint, dass auf $unit($target) kein Zauber liegt."</text>
-    <text locale="en">"It appears to $unit($mage) that $unit($target) is not charmed."</text>
   </message>
   <message name="analyse_region_nospell" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) meint, dass auf $region($region) kein Zauber liegt."</text>
-    <text locale="en">"It appears to $unit($mage) that $region($region) is not charmed."</text>
   </message>
   <message name="spellregionresists" section="magic">
     <type>
@@ -2224,8 +1682,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Region konnte nicht verzaubert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The region could not be charmed."</text>
   </message>
   <message name="spellshipresists" section="magic">
     <type>
@@ -2234,8 +1690,6 @@
       <arg name="command" type="order"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $ship($ship) widersteht dem Zauber."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $ship($ship) resists the spell."</text>
   </message>
   <message name="spellbuildingresists" section="magic">
     <type>
@@ -2244,8 +1698,6 @@
       <arg name="command" type="order"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Gebäude $int36($id) konnte nicht verzaubert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Building $int36($id) could not be charmed."</text>
   </message>
   <message name="spellunitresists" section="magic">
     <type>
@@ -2254,8 +1706,6 @@
       <arg name="command" type="order"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($target) widersteht dem Zauber."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($target) resists the spell."</text>
   </message>
   <message name="spellshipnotfound" section="magic">
     <type>
@@ -2264,8 +1714,6 @@
       <arg name="command" type="order"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Schiff $int36($id) wurde nicht gefunden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Ship $int36($id) could not be located."</text>
   </message>
   <message name="spellbuildingnotfound" section="magic">
     <type>
@@ -2274,8 +1722,6 @@
       <arg name="command" type="order"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Gebäude $int36($id) wurde nicht gefunden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Building $int36($id) could not be located."</text>
   </message>
   <message name="unitnotfound_id" section="errors">
     <type>
@@ -2284,8 +1730,6 @@
       <arg name="command" type="order"/>
       <arg name="id" type="string"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Einheit $id wurde nicht gefunden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Unit $id could not be located."</text>
   </message>
   <message name="spelltargetnotfound" section="magic">
     <type>
@@ -2293,16 +1737,12 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es wurde kein Ziel gefunden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The spell could not find a target."</text>
   </message>
   <message name="shock" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="reason" type="string"/>
     </type>
-    <text locale="de">"$unit($mage) erleidet durch den Tod seines Vertrauten einen Schock."</text>
-    <text locale="en">"$unit($mage) receives a shock when his familiar dies."</text>
   </message>
   <message name="missing_force" section="magic">
     <type>
@@ -2310,8 +1750,6 @@
       <arg name="level" type="int"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"$unit($unit) schafft es nicht, genug Kraft aufzubringen, um $spell($spell) auf Stufe $int($level) zu zaubern."</text>
-    <text locale="en">"$unit($unit) cannot muster enough energy to cast $spell($spell) on level $int($level)."</text>
   </message>
   <message name="missing_components_list" section="errors">
     <type>
@@ -2320,8 +1758,6 @@
       <arg name="command" type="order"/>
       <arg name="list" type="resources"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Für diesen Zauber fehlen noch $resources($list)."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Casting this spell requires an additional $resources($list)."</text>
   </message>
   <message name="missing_components" section="magic">
     <type>
@@ -2329,8 +1765,6 @@
       <arg name="level" type="int"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"$unit($unit) hat nicht genügend Komponenten um $spell($spell) auf Stufe $int($level) zu zaubern."</text>
-    <text locale="en">"$unit($unit) has insufficient components to cast $spell($spell) on level $int($level)."</text>
   </message>
   <message name="patzer" section="magic">
     <type>
@@ -2338,8 +1772,6 @@
       <arg name="region" type="region"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"$unit($unit) unterläuft in $region($region) beim Zaubern von $spell($spell) ein Patzer."</text>
-    <text locale="en">"$unit($unit) fumbles while casting $spell($spell) in $region($region)."</text>
   </message>
   <message name="patzer3" section="magic">
     <type>
@@ -2347,8 +1779,6 @@
       <arg name="region" type="region"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"Als $unit($unit) in $region($region) versucht, $spell($spell) zu zaubern, scheint plötzlich ein Beben durch die magische Essenz zu laufen und ein furchtbarer Sog versucht $unit($unit) in eine andere Dimension zu ziehen. Mit letzter Kraft gelingt es $unit($unit) sich zu retten."</text>
-    <text locale="en">"When $unit($unit) in $region($region) tries to cast $spell($spell), a sudden disturbance ripples through the magical realm and a terrible force attempts to drag the magician to another dimension. However, with a final effort of strength, $unit($unit) manages to save himself."</text>
   </message>
   <message name="patzer4" section="magic">
     <type>
@@ -2356,8 +1786,6 @@
       <arg name="region" type="region"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"Als $unit($unit) in $region($region) versucht, $spell($spell) zu zaubern erhebt sich plötzlich ein dunkler Wind. Bizarre geisterhafte Gestalten kreisen um den Magier und scheinen sich von den magischen Energien des Zaubers zu ernähren. Mit letzter Kraft gelingt es $unit($unit) dennoch den Spruch zu zaubern."</text>
-    <text locale="en">"When $unit($unit) in $region($region) tries to cast $spell($spell), strong winds suddenly rise. Bizarre ghostlike creatures circle around the magician and seem to be leeching magical energy. However, with a final effort of strength, $unit($unit) manages to complete the spell."</text>
   </message>
   <message name="patzer6" section="magic">
     <type>
@@ -2365,8 +1793,6 @@
       <arg name="region" type="region"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"Eine Botschaft von $unit.dative($unit) in $region($region): 'Ups! Quack, Quack!'"</text>
-    <text locale="en">"A message from $unit($unit) in $region($region): 'Oops! Croak, Croak!'"</text>
   </message>
   <message name="familiar_farcast" section="errors">
     <type>
@@ -2375,8 +1801,6 @@
       <arg name="command" type="order"/>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($mage) kann Zauber, die durch $unit($unit) gewirkt werden, nicht zusätzlich in die Ferne richten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($mage) cannot direct spells that are channeled through $unit($unit) into distant regions."</text>
   </message>
   <message name="familiar_toofar" section="errors">
     <type>
@@ -2385,8 +1809,6 @@
       <arg name="command" type="order"/>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($mage) kann nicht genug Energie aufbringen, um diesen Spruch durch $unit($unit) zu wirken."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($mage) cannot raise enough energy to channel the spell through $unit($unit)."</text>
   </message>
   <message name="familiar_describe" section="magic">
     <type>
@@ -2394,8 +1816,6 @@
       <arg name="skills" type="string"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($mage) ruft einen Vertrauten. $race($race, 0) können $skills lernen."</text>
-    <text locale="en">"$unit($mage) summons a familiar. $race($race, 0) can learn ${skills}."</text>
   </message>
 
   <message name="babbler_resist" section="magic">
@@ -2403,16 +1823,12 @@
       <arg name="unit" type="unit"/>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) hat einen feuchtfröhlichen Abend in der Taverne verbracht. Ausser einem fürchterlichen Brummschädel ist da auch noch das dumme Gefühl $unit($mage) seine ganze Lebensgeschichte erzählt zu haben."</text>
-    <text locale="en">"$unit($unit) spent the evening carousing in the tavern. In addition to a terrible headache, there remains this feeling of having told $unit($mage) the story of his entire life."</text>
   </message>
 
   <message name="babbler_effect" section="magic">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) hat einen feuchtfröhlichen Abend in der Taverne verbracht. Ausser einem fürchterlichen Brummschädel ist da auch noch das dumme Gefühl die ganze Taverne mit seiner Lebensgeschichte unterhalten zu haben."</text>
-    <text locale="en">"$unit($unit) spent the evening carousing in the tavern. In addition to a terrible headache, there remains this feeling of having told everyone the story of his entire life."</text>
   </message>
 
   <message name="charming_effect" section="magic">
@@ -2421,8 +1837,6 @@
       <arg name="mage" type="unit"/>
       <arg name="duration" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) gelingt es $unit($unit) zu verzaubern. $unit($unit) wird für etwa $int($duration) Wochen unseren Befehlen gehorchen."</text>
-    <text locale="en">"$unit($mage) chamrs $unit($unit). $unit($unit) will obey our orders for approximatley $int($duration) more weeks."</text>
   </message>
 
   <message name="spell_resist" section="magic">
@@ -2431,8 +1845,6 @@
       <arg name="region" type="region"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"$unit($unit) gelingt es $spell($spell) zu zaubern, doch der Spruch zeigt keine Wirkung."</text>
-    <text locale="en">"$unit($unit) manages to cast $spell($spell), but the spell seems to have no effect."</text>
   </message>
   <message name="patzer5" section="magic">
     <type>
@@ -2440,16 +1852,12 @@
       <arg name="region" type="region"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"$unit($unit) fühlt sich nach dem Zaubern von $spell($spell) viel erschöpfter als sonst und hat das Gefühl, dass alle weiteren Zauber deutlich mehr Kraft als normalerweise kosten werden."</text>
-    <text locale="en">"$unit($unit) feels far more exhausted than he should after casting $spell($spell) and assumes that any following spells will cost far more energy than usual."</text>
   </message>
   <message name="patzer2" section="magic">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) hat rasende Kopfschmerzen und kann sich nicht mehr richtig konzentrieren. Irgendwas bei diesem Zauber ist fürchterlich schiefgelaufen."</text>
-    <text locale="en">"$unit($unit) in $region($region) is hit by a massive headache and cannot concentrate on the spell. Some part of this ritual has gone very wrong indeed."</text>
   </message>
   <message name="magic_fumble" section="magic">
     <type>
@@ -2457,12 +1865,8 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Magier verfängt sich im eigenen Zauber."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The magician is caught in their own spell."</text>
   </message>
   <message name="xmastree_effect" section="magic">
-    <text locale="de">"In der Region erstrahlen des Nachts bunte Lichter, Gloeckchen klingeln und frohes Kindergelaechter klingt durch den Wald."</text>
-    <text locale="en">"At night, colourful lights can be seen in this region, bells are a-ringing and the laughter of happy children seems to be everywhere in the forests."</text>
   </message>
   <message name="weakmagic" section="magic">
     <type>
@@ -2470,8 +1874,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Zauber von $unit.dative($unit) war viel zu schwach und löst sich gleich wieder auf."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The spell of $unit($unit) was way to weak and its magic dissolves immediately."</text>
   </message>
   <message name="objmagic_effect" section="magic">
     <type>
@@ -2480,8 +1882,6 @@
       <arg name="command" type="order"/>
       <arg name="target" type="string"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) verzaubert ${target}."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) puts a spell on ${target}."</text>
   </message>
   <message name="regionmagic_patzer" section="magic">
     <type>
@@ -2489,8 +1889,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) gelingt es zwar die Region zu verzaubern, aber irgendwas ging schief."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) manages to put a spell on the region, but something went wrong nonetheless."</text>
   </message>
   <message name="regionmagic_effect" section="magic">
     <type>
@@ -2498,16 +1896,12 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) gelingt es die Region zu verzaubern."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) puts a spell on the region."</text>
   </message>
   <message name="effectstrength" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) erhöht die Körperkraft von $unit.dative($target) beträchtlich."</text>
-    <text locale="en">"$unit($mage) increases the strength of $unit($target) dramatically."</text>
   </message>
   <message name="regenaura" section="magic">
     <type>
@@ -2515,8 +1909,6 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) regeneriert $int($amount) Aura."</text>
-    <text locale="en">"$unit($unit) regenerates $int($amount) aura in $region($region)."</text>
   </message>
   <message name="studycost" section="study">
     <type>
@@ -2525,16 +1917,12 @@
       <arg name="cost" type="int"/>
       <arg name="skill" type="skill"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) verbraucht $int($cost) Silber für das Studium von $skill($skill)."</text>
-    <text locale="en">"$unit($unit) spends $int($cost) silver in $region($region) to study $skill($skill)."</text>
   </message>
   <message name="teachdumb" section="study">
     <type>
       <arg name="teacher" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($teacher) kann durch Dumpfbackenbrot nur $int($amount) Schüler lehren."</text>
-    <text locale="en">"Due to the effect of duncebuns, $unit($teacher) can only teach $int($amount) students."</text>
   </message>
   <message name="teach_teacher" section="study">
     <type>
@@ -2543,8 +1931,6 @@
       <arg name="skill" type="skill"/>
       <arg name="level" type="int"/>
     </type>
-    <text locale="de">"$unit($teacher) lehrt $unit($student) $skill($skill) auf Stufe $int($level)."</text>
-    <text locale="en">"$unit($teacher) teaches $unit($student) $skill($skill) to level $int($level)."</text>
   </message>
   <message name="teach_student" section="study">
     <type>
@@ -2552,8 +1938,6 @@
       <arg name="student" type="unit"/>
       <arg name="skill" type="skill"/>
     </type>
-    <text locale="de">"$unit($teacher) lehrt $unit($student) $skill($skill)."</text>
-    <text locale="en">"$unit($teacher) teaches $unit($student) $skill($skill)."</text>
   </message>
   <message name="sellamount" section="economy">
     <type>
@@ -2561,8 +1945,6 @@
       <arg name="amount" type="int"/>
       <arg name="resource" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) verkauft $int($amount) $resource($resource,$amount)."</text>
-    <text locale="en">"$unit($unit) sells $int($amount) $resource($resource,$amount)."</text>
   </message>
   <message name="buyamount" section="economy">
     <type>
@@ -2570,16 +1952,12 @@
       <arg name="amount" type="int"/>
       <arg name="resource" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) kauft $int($amount) $resource($resource,$amount)."</text>
-    <text locale="en">"$unit($unit) buys $int($amount) $resource($resource,$amount)."</text>
   </message>
   <message name="buy" section="economy">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="money" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) bezahlt $int($money) Silber für den Kauf von Luxusgütern."</text>
-    <text locale="en">"$unit($unit) pays $int($money) silver for luxury items."</text>
   </message>
   <message name="income_trade" section="economy">
     <type>
@@ -2587,8 +1965,6 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) verdient in $region($region) $int($amount) Silber durch den Verkauf von Luxusgütern."</text>
-    <text locale="en">"$unit($unit) earned $int($amount) silver in $region($region) by selling luxury items."</text>
   </message>
   <message name="income_work_reduced" section="economy">
     <type>
@@ -2597,8 +1973,6 @@
       <arg name="amount" type="int"/>
       <arg name="wanted" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) arbeitet in $region($region) für einen Lohn von $int($amount)$if($eq($wanted,$amount),""," statt $int($wanted)") Silber."</text>
-    <text locale="en">"$unit($unit) works in $region($region) for a wage of $int($amount) $if($eq($wanted,$amount),""," out of $int($wanted)") silver."</text>
   </message>
   <message name="income_work" section="economy">
     <type>
@@ -2606,8 +1980,6 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) arbeitet in $region($region) für einen Lohn von $int($amount) Silber."</text>
-    <text locale="en">"In $region($region), $unit($unit) works for a wage of $int($amount) silver."</text>
   </message>
   <message name="income_entertainment_reduced" section="economy">
     <type>
@@ -2616,8 +1988,6 @@
       <arg name="amount" type="int"/>
       <arg name="wanted" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) verdient in $region($region) $int($amount)$if($eq($wanted,$amount),""," statt $int($wanted)") Silber durch Unterhaltung."</text>
-    <text locale="en">"In $region($region), $unit($unit) earns only $int($amount) instead of$if($eq($wanted,$amount),""," of$if($eq($wanted,$amount),""," of $int($wanted)") ") with entertainment."</text>
   </message>
   <message name="income_fishing" section="economy">
     <type>
@@ -2625,8 +1995,6 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) fängt in $region($region) Fische im Wert von $int($amount) Silber."</text>
-    <text locale="en">"In $region($region), $unit($unit) catches fish worth $int($amount) silver."</text>
   </message>
   <message name="income_entertainment" section="economy">
     <type>
@@ -2634,8 +2002,6 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) verdient in $region($region) $int($amount) Silber durch Unterhaltung."</text>
-    <text locale="en">"$unit($unit) earns $int($amount) in $region($region) with entertainment."</text>
   </message>
   <message name="income_magic_reduced" section="economy">
     <type>
@@ -2644,8 +2010,6 @@
       <arg name="amount" type="int"/>
       <arg name="wanted" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) verdient in $region($region) $int($amount)$if($eq($wanted,$amount),""," statt $int($wanted)") Silber durch Zauberei."</text>
-    <text locale="en">"$unit($unit) in $region($region) earns $int($amount)$if($eq($wanted,$amount),""," instead of $int($wanted)") silver through magic."</text>
   </message>
   <message name="income_magic" section="economy">
     <type>
@@ -2653,8 +2017,6 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) verdient in $region($region) $int($amount) Silber durch Zauberei."</text>
-    <text locale="en">"$unit($unit) earns $int($amount) silver through simple magical services in $region($region)."</text>
   </message>
   <message name="income_steal_reduced" section="economy">
     <type>
@@ -2663,8 +2025,6 @@
       <arg name="amount" type="int"/>
       <arg name="wanted" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) klaut in $region($region) $int($amount)$if($eq($wanted,$amount),""," statt $int($wanted)") Silber."</text>
-    <text locale="en">"$unit($unit) steals only $int($amount) silver instead of$if($eq($wanted,$amount),""," of$if($eq($wanted,$amount),""," of $int($wanted)") ") in $region($region)."</text>
   </message>
   <message name="income_steal" section="economy">
     <type>
@@ -2672,8 +2032,6 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) klaut in $region($region) $int($amount) Silber."</text>
-    <text locale="en">"$unit($unit) steals $int($amount) silver in $region($region)."</text>
   </message>
   <message name="income_tax_reduced" section="economy">
     <type>
@@ -2682,8 +2040,6 @@
       <arg name="amount" type="int"/>
       <arg name="wanted" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) treibt in $region($region) Steuern in Höhe von $int($amount)$if($eq($wanted,$amount),""," statt $int($wanted)") Silber ein."</text>
-    <text locale="en">"$unit($unit) collects taxes of$if($eq($wanted,$amount),""," only") $int($amount) silver$if($eq($wanted,$amount),""," instead of $int($wanted) silver") ") in $region($region)."</text>
   </message>
   <message name="income_tax" section="economy">
     <type>
@@ -2691,8 +2047,6 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) treibt in $region($region) Steuern in Höhe von $int($amount) Silber ein."</text>
-    <text locale="en">"$unit($unit) collects taxes of $int($amount) silver in $region($region)."</text>
   </message>
   <message name="income" section="economy">
     <type>
@@ -2702,8 +2056,6 @@
       <arg name="wanted" type="int"/>
       <arg name="mode" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) verdient$if($eq($mode,4)," am Handel","") in $region($region) $int($amount)$if($eq($wanted,$amount),""," statt $int($wanted)") Silber$if($eq($mode,1)," durch Unterhaltung",$if($eq($mode,2)," durch Steuern",$if($eq($mode,3)," durch Handel",$if($eq($mode,5)," durch Diebstahl",$if($eq($mode,6)," durch Zauberei",$if($eq($mode,7)," durch Plündern",""))))))."</text>
-    <text locale="en">"$unit($unit) earns $int($amount)$if($eq($wanted,$amount),""," of $int($wanted)") in $region($region) $if($eq($mode,1)," by entertainment",$if($eq($mode,2)," by taxes",$if($eq($mode,3)," by trade",$if($eq($mode,5)," by stealing",$if($eq($mode,6)," by magic",$if($eq($mode,7)," by pillaging",""))))))."</text>
   </message>
   <message name="herbfound" section="production">
     <type>
@@ -2712,16 +2064,12 @@
       <arg name="amount" type="int"/>
       <arg name="herb" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) findet $int($amount) $resource($herb,$amount)."</text>
-    <text locale="en">"$unit($unit) in $region($region) finds $int($amount) $resource($herb,$amount)."</text>
   </message>
   <message name="raised" section="production">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) züchtet $int($amount) Pferde."</text>
-    <text locale="en">"$unit($unit) breeds $int($amount) horses."</text>
   </message>
   <message name="plant" section="production">
     <type>
@@ -2730,23 +2078,17 @@
       <arg name="amount" type="int"/>
       <arg name="herb" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) pflanzt in $region($region) $int($amount) $resource($herb,$amount)."</text>
-    <text locale="en">"$unit($unit) plants $int($amount) $resource($herb,$amount) in $region($region)."</text>
   </message>
   <message name="unveileog" section="production">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) entdeckt eine Laenader."</text>
-    <text locale="en">"$unit($unit) discovers laen in $region($region)."</text>
   </message>
   <message name="emptyeog" section="production">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Die Laenader in $region($region) ist erschöpft."</text>
-    <text locale="en">"There is no more laen left in $region($region)."</text>
   </message>
   <message name="produce_lowskill" section="errors">
     <type>
@@ -2754,8 +2096,6 @@
       <arg name="region" type="region"/>
       <arg name="resource" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) hat ein zu niedriges Talent, um $resource($resource,0) abzubauen."</text>
-    <text locale="en">"$unit($unit) in $region($region) is not proficient enough to produce $resource($resource,0)."</text>
   </message>
   <message name="produce" section="production">
     <type>
@@ -2765,8 +2105,6 @@
       <arg name="wanted" type="int"/>
       <arg name="resource" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) produziert $int($amount)$if($eq($wanted,$amount),""," von $int($wanted)") $resource($resource,$wanted)."</text>
-    <text locale="en">"$unit($unit) in $region($region) produces $int($amount)$if($eq($wanted,$amount),""," of $int($wanted)") $resource($resource,$amount)."</text>
   </message>
     <message name="buildbuilding" section="production">
     <type>
@@ -2774,8 +2112,6 @@
       <arg name="size" type="int"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($unit) baut für $int($size) an $building($building) weiter."</text>
-    <text locale="en">"$unit($unit) builds $int($size) more on $building($building)."</text>
   </message>
   <message name="buildship" section="production">
     <type>
@@ -2783,24 +2119,18 @@
       <arg name="size" type="int"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"$unit($unit) baut für $int($size) an $ship($ship) weiter."</text>
-    <text locale="en">"$unit($unit) builds $int($size) more on $ship($ship)."</text>
   </message>
   <message name="firewall_death" section="movement">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) stirbt beim Versuch, die Feuerwand nach $region($region) zu durchqueren."</text>
-    <text locale="en">"$unit($unit) dies trying to cross the wall of fire into $region($region)."</text>
   </message>
   <message name="firewall_damage" section="movement">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) erleidet beim Durchqueren der Feuerwand nach $region($region) schwere Verbrennungen."</text>
-    <text locale="en">"$unit($unit) steps through the wall of fire into $region($region) and receives severe burn damage."</text>
   </message>
   <message name="transport" section="movement">
     <type>
@@ -2809,8 +2139,6 @@
       <arg name="start" type="region"/>
       <arg name="end" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) transportiert $unit($target) von $region($start) nach $region($end)."</text>
-    <text locale="en">"$unit($unit) transported $unit($target) from $region($start) to $region($end)."</text>
   </message>
   <message name="travel" section="movement">
     <type>
@@ -2820,8 +2148,6 @@
       <arg name="end" type="region"/>
       <arg name="regions" type="regions"/>
     </type>
-    <text locale="de">"$unit($unit) $if($eq($mode,1),"reitet", "wandert") von $region($start) nach $region($end).$if($isnull($regions),""," Dabei wurde $trail($regions) durchquert.")"</text>
-    <text locale="en">"$unit($unit) $if($eq($mode,1),"rides", "walks") from $region($start) to $region($end)$if($isnull($regions),""," by way of $trail($regions)")."</text>
   </message>
   <message name="detectocean" section="errors">
     <type>
@@ -2829,72 +2155,54 @@
       <arg name="region" type="region"/>
       <arg name="terrain" type="string"/>
     </type>
-    <text locale="de">"$unit($unit) entdeckt, dass $region($region) $localize($terrain) ist."</text>
-    <text locale="en">"$unit($unit) discovered that $region($region) is $localize($terrain)."</text>
   </message>
   <message name="leftship" section="errors">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) ist in dieser Runde gelandet und kann nicht weiter ins Landesinnere nach $region($region) vorstossen."</text>
-    <text locale="en">"$unit($unit) has just landed and cannot continue moving to $region($region)."</text>
   </message>
   <message name="sailnolandingstorm" section="errors">
     <type>
       <arg name="ship" type="ship"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Die Mannschaft der $ship($ship) kann in letzter Sekunde verhindern, dass das Schiff in $region($region) auf Land aufläuft."</text>
-    <text locale="en">"At the very last moment, the crew of the $ship($ship) saved the ship from running aground in $region($region)."</text>
   </message>
   <message name="sailnolanding" section="errors">
     <type>
       <arg name="ship" type="ship"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Die $ship($ship) konnte in $region($region) nicht einreisen, die Küste ist zu gefährlich für das Schiff."</text>
-    <text locale="en">"The $ship($ship) could not berth in $region($region). The coast is too dangerous for the vessel."</text>
   </message>
   <message name="sailforbiddendir" section="errors">
     <type>
       <arg name="ship" type="ship"/>
       <arg name="direction" type="direction"/>
     </type>
-    <text locale="de">"Die Mannschaft der $ship($ship) weigert sich, nach $direction($direction) zu reisen."</text>
-    <text locale="en">"The crew of the $ship($ship) refuses to travel to the $direction($direction)."</text>
   </message>
   <message name="sailforbidden" section="errors">
     <type>
       <arg name="ship" type="ship"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Die Mannschaft der $ship($ship) weigert sich, nach $region($region) zu reisen."</text>
-    <text locale="en">"The crew of the $ship($ship) refuses to travel to $region($region)."</text>
   </message>
   <message name="detectforbiddendir" section="errors">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="direction" type="direction"/>
     </type>
-    <text locale="de">"$unit($unit) weigert sich, nach $direction($direction) zu reisen."</text>
-    <text locale="en">"$unit($unit) refuses to travel to the $direction($direction)."</text>
   </message>
   <message name="detectforbidden" section="errors">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) weigert sich, nach $region($region) zu reisen."</text>
-    <text locale="en">"$unit($unit) refuses to travel to $region($region)."</text>
   </message>
   <message name="sailfail" section="errors">
     <type>
       <arg name="ship" type="ship"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Die $ship($ship) konnte $region($region) nicht verlassen."</text>
-    <text locale="en">"The $ship($ship) could not leave $region($region)."</text>
   </message>
   <message name="moveblockedbyguard" section="errors">
     <type>
@@ -2902,8 +2210,6 @@
       <arg name="region" type="region"/>
       <arg name="guard" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) wurde in $region($region) von $unit.dative($guard) aufgehalten."</text>
-    <text locale="en">"$unit($unit) was kept in $region($region) by $unit($guard)."</text>
   </message>
   <message name="regionowned" section="errors">
     <type>
@@ -2911,40 +2217,30 @@
       <arg name="region" type="region"/>
       <arg name="target" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) konnte nicht von $region($region) nach $region($target) reisen, da der Besitzer der Region es verhinderte."</text>
-    <text locale="en">"$unit($unit) could not travel from $region($region) to $region($target) because the owner denied entrance."</text>
   </message>
   <message name="leavefail" section="errors">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) konnte aus $region($region) nicht ausreisen."</text>
-    <text locale="en">"$unit($unit) could not leave $region($region)."</text>
   </message>
   <message name="followdetect" section="movement">
     <type>
       <arg name="follower" type="unit"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($follower) ist $unit($unit) gefolgt."</text>
-    <text locale="en">"$unit($follower) followed $unit($unit)."</text>
   </message>
   <message name="followfail" section="movement">
     <type>
       <arg name="follower" type="unit"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($follower) konnte $unit($unit) nicht folgen."</text>
-    <text locale="en">"$unit($follower) could not follow $unit($unit)."</text>
   </message>
   <message name="moveblocked" section="errors">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="direction" type="direction"/>
     </type>
-    <text locale="de">"$unit($unit) entdeckt, dass es keinen Weg nach $direction($direction) gibt."</text>
-    <text locale="en">"$unit($unit) discovers that there is no route going $direction($direction)."</text>
   </message>
   <message name="fogblock" section="errors">
     <type>
@@ -2952,22 +2248,16 @@
       <arg name="region" type="region"/>
       <arg name="direction" type="direction"/>
     </type>
-    <text locale="de">"$unit($unit) konnte von $region($region) nicht nach $direction($direction) ausreisen, der Nebel war zu dicht."</text>
-    <text locale="en">"$unit($unit) could not travel $direction($direction) from $region($region), the fog was too dense."</text>
   </message>
   <message name="entrise" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"In $region($region) erschienen die Herren der Bäume."</text>
-    <text locale="en">"In $region($region), the Lords of the Trees have risen."</text>
   </message>
   <message name="undeadrise" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"In $region($region) erhoben sich die Toten aus den Gräbern."</text>
-    <text locale="en">"The dead rise from their graves in $region($region)."</text>
   </message>
   <message name="orcgrowth" section="events">
     <type>
@@ -2975,30 +2265,22 @@
       <arg name="amount" type="int"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) vermehrt sich um $int($amount) $race($race,$amount)."</text>
-    <text locale="en">"$unit($unit) breeds $int($amount) new $race($race,$amount)."</text>
   </message>
   <message name="renamed_faction_notseen" section="events">
     <type>
   </type>
-    <text locale="de">"Die Partei bekommt einen Spitznamen."</text>
-    <text locale="en">"Your faction received a nickname."</text>
   </message>
   <message name="renamed_faction_seen" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Die Partei bekommt von $unit.dative($unit) in $region($region) einen Spitznamen."</text>
-    <text locale="en">"Your faction received a nickname from $unit($unit) in $region($region)."</text>
   </message>
   <message name="renamed_building_notseen" section="events">
     <type>
       <arg name="building" type="building"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$building($building) in $region($region) bekommt einen Spitznamen."</text>
-    <text locale="en">"$building($building) in $region($region) received a nickname."</text>
   </message>
   <message name="renamed_building_seen" section="events">
     <type>
@@ -3006,16 +2288,12 @@
       <arg name="region" type="region"/>
       <arg name="renamer" type="unit"/>
     </type>
-    <text locale="de">"$building($building) in $region($region) bekommt von $unit.dative($renamer) einen Spitznamen."</text>
-    <text locale="en">"$building($building) in $region($region) received a nickname from $unit($renamer)."</text>
   </message>
   <message name="renamed_ship_notseen" section="events">
     <type>
       <arg name="ship" type="ship"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Die $ship($ship) in $region($region) bekommt einen Spitznamen."</text>
-    <text locale="en">"$ship($ship) in $region($region) received a nickname."</text>
   </message>
   <message name="renamed_ship_seen" section="events">
     <type>
@@ -3023,16 +2301,12 @@
       <arg name="region" type="region"/>
       <arg name="renamer" type="unit"/>
     </type>
-    <text locale="de">"Die $ship($ship) in $region($region) bekommt von $unit.dative($renamer) einen Spitznamen."</text>
-    <text locale="en">"$ship($ship) in $region($region) received a nickname from $unit($renamer)."</text>
   </message>
   <message name="renamed_notseen" section="events">
     <type>
       <arg name="renamed" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($renamed) in $region($region) bekommt einen Spitznamen."</text>
-    <text locale="en">"$unit($renamed) in $region($region) received a nickname."</text>
   </message>
   <message name="renamed_seen" section="events">
     <type>
@@ -3040,30 +2314,22 @@
       <arg name="region" type="region"/>
       <arg name="renamer" type="unit"/>
     </type>
-    <text locale="de">"$unit($renamed) in $region($region) bekommt von $unit.dative($renamer) einen Spitznamen."</text>
-    <text locale="en">"$unit($renamed) in $region($region) received a nickname from $unit($renamer)."</text>
   </message>
   <message name="phunger" section="events">
     <type>
       <arg name="dead" type="int"/>
     </type>
-    <text locale="de">"$if($eq($dead,1),"Ein Bauer verhungert","$int($dead) Bauern verhungern")."</text>
-    <text locale="en">"$if($eq($dead,1),"One peasant starves","$int($dead) peasants starve")."</text>
   </message>
   <message name="volcanooutbreaknn" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Der Vulkan in $region($region) bricht aus."</text>
-    <text locale="en">"The volcano in $region($region) erupts."</text>
   </message>
   <message name="volcanooutbreak" section="events">
     <type>
       <arg name="regionv" type="region"/>
       <arg name="regionn" type="region"/>
     </type>
-    <text locale="de">"Der Vulkan in $region($regionv) bricht aus. Die Lavamassen verwüsten $region($regionn)."</text>
-    <text locale="en">"The volcano in $region($regionv) erupts. The lava devastates $region($regionn)."</text>
   </message>
   <message name="volcano_dead" section="events">
     <type>
@@ -3071,30 +2337,22 @@
       <arg name="dead" type="int"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"Beim Vulkanausbruch in $region($region) sterben $int($dead) Personen in $unit($unit)."</text>
-    <text locale="en">"$int($dead) people in $unit($unit) perish when the volcano in $region($region) erupts."</text>
   </message>
   <message name="volcanostopsmoke" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Aus dem Vulkankrater von $region($region) steigt kein Rauch mehr."</text>
-    <text locale="en">"The volcano of $region($region) stops releasing smoke."</text>
   </message>
   <message name="volcanostartsmoke" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Aus dem Vulkankrater von $region($region) steigt plötzlich Rauch."</text>
-    <text locale="en">"Columns of smoke are released by the volcano of $region($region)."</text>
   </message>
   <message name="desertion" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) desertiert."</text>
-    <text locale="en">"$unit($unit) in $region($region) abandons your cause."</text>
   </message>
   <message name="destroy_road" section="events">
     <type>
@@ -3102,16 +2360,12 @@
       <arg name="from" type="region"/>
       <arg name="to" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) reißt die Straße zwischen $region($from) und $region($to) ein."</text>
-    <text locale="en">"$unit($unit) demolishes the road between $region($from) and $region($to)."</text>
   </message>
   <message name="researchherb_none" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) kann keine Kräuter finden."</text>
-    <text locale="en">"$unit($unit) could not find any herbs in $region($region)."</text>
   </message>
   <message name="researchherb" section="events">
     <type>
@@ -3120,24 +2374,18 @@
       <arg name="herb" type="resource"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) stellt fest, dass es hier $localize($amount) $resource($herb,0) gibt."</text>
-    <text locale="en">"$unit($unit) discovers that $localize($amount) $resource($herb,0) grow in $region($region)."</text>
   </message>
   <message name="destroy_partial" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($unit) reißt einen Teil von $building($building) ein."</text>
-    <text locale="en">"$unit($unit) tears down parts of $building($building)."</text>
   </message>
   <message name="destroy" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($unit) zerstört $building($building)."</text>
-    <text locale="en">"$unit($unit) destroys $building($building)."</text>
   </message>
   <message name="buildroad" section="events">
     <type>
@@ -3145,8 +2393,6 @@
       <arg name="region" type="region"/>
       <arg name="size" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) erweitert in $region($region) das Straßennetz um $int($size)."</text>
-    <text locale="en">"$unit($unit) extends the road network in $region($region) by $int($size)."</text>
   </message>
   <message name="scunicorn" section="events">
     <type>
@@ -3154,16 +2400,12 @@
       <arg name="amount" type="int"/>
       <arg name="rtype" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) $if($eq($amount,1),"schließt","schließen") sich $int($amount) $resource($rtype,$amount) an."</text>
-    <text locale="en">"$int($amount) $resource($rtype,$amount) $if($eq($amount,1),"joins","join") $unit($unit)."</text>
   </message>
   <message name="itemcloak" section="events">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) legt einen Schleier um die Ausrüstung von $unit.dative($target)."</text>
-    <text locale="en">"$unit($mage) shrouds the equipment of $unit($target) in shadows."</text>
   </message>
   <message name="piratesawvictim" section="events">
     <type>
@@ -3172,8 +2414,6 @@
       <arg name="region" type="region"/>
       <arg name="dir" type="direction"/>
     </type>
-    <text locale="de">"$if($isnull($ship),"$unit($unit)","Die $ship($ship)") in $region($region) entdeckt ein Opfer im $direction($dir)."</text>
-    <text locale="en">"$if($isnull($ship),"$unit($unit)","The $ship($ship)") in $region($region) made $direction($dir) a target."</text>
   </message>
   <message name="piratenovictim" section="events">
     <type>
@@ -3181,22 +2421,16 @@
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$if($isnull($ship),"$unit($unit)","Die $ship($ship)") in $region($region) kann keine Schiffe aufbringen."</text>
-    <text locale="en">"$if($isnull($ship),"$unit($unit)","The $ship($ship)") could not capture other ships in $region($region)."</text>
   </message>
   <message name="deorcified" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Langsam kehren andere Völker nach $region($region) zurück."</text>
-    <text locale="en">"Little by little, people return to $region($region)."</text>
   </message>
   <message name="orcified" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Vor den vielen Orks in $region($region) fliehen die anderen Einwohner."</text>
-    <text locale="en">"People in $region($region) flee because of too many orcs."</text>
   </message>
   <message name="shipdestroy_partial" section="events">
     <type>
@@ -3204,8 +2438,6 @@
       <arg name="region" type="region"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) beschädigt die $ship($ship)."</text>
-    <text locale="en">"$unit($unit) in $region($region) damages the $ship($ship)."</text>
   </message>
   <message name="shipdestroy" section="events">
     <type>
@@ -3213,23 +2445,17 @@
       <arg name="region" type="region"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) versenkt die $ship($ship)."</text>
-    <text locale="en">"$unit($unit) sunk $ship($ship) in $region($region)."</text>
   </message>
   <message name="illusionantimagic" section="events">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) marschiert in eine Antimagiezone und löst sich auf."</text>
-    <text locale="en">"$unit($unit) walks into an antimagical zone and dissolves."</text>
   </message>
   <message name="fleescared" section="events">
     <type>
       <arg name="amount" type="int"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$int($amount) Bauern flohen aus Furcht vor $unit($unit)."</text>
-    <text locale="en">"$int($amount) peasants fled in fear of $unit($unit)."</text>
   </message>
   <message name="absorbpeasants" section="events">
     <type>
@@ -3237,59 +2463,43 @@
       <arg name="amount" type="int"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$int($amount) Bauern werden zu $race($race,0) und schliessen sich $unit($unit) an."</text>
-    <text locale="en">"$int($amount) peasants become $race($race,0) and join the ranks of $unit($unit)."</text>
   </message>
   <message name="eathorse" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) verspeiste $int($amount) Pferde."</text>
-    <text locale="en">"$unit($unit) ate $int($amount) horses."</text>
   </message>
   <message name="eatpeasants" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) verspeiste $int($amount) Bauern."</text>
-    <text locale="en">"$unit($unit) ate $int($amount) peasants."</text>
   </message>
   <message name="wrongpasswd" section="events">
     <type>
       <arg name="password" type="string"/>
     </type>
-    <text locale="de">"Deine Befehle hatten ein falsches Passwort (${password})."</text>
-    <text locale="en">"Your orders had the wrong password (${password})."</text>
   </message>
   <message name="changepasswd" section="events">
     <type>
       <arg name="value" type="string"/>
     </type>
-    <text locale="de">"Das Passwort für diese Partei lautet ${value}."</text>
-    <text locale="en">"The password of this faction is '$value'."</text>
   </message>
   <message name="changemail_invalid" section="events">
     <type>
       <arg name="value" type="string"/>
     </type>
-    <text locale="de">"Die Reportadresse wurde nicht geändert, '${value}' ist keine gültige email."</text>
-    <text locale="en">"Address not changed, '$value' is an invalid email."</text>
   </message>
   <message name="changemail" section="events">
     <type>
       <arg name="value" type="string"/>
     </type>
-    <text locale="de">"Die Reportadresse wurde auf ${value} geändert."</text>
-    <text locale="en">"Address has been changed to '$value'."</text>
   </message>
   <message name="changebanner" section="events">
     <type>
       <arg name="value" type="string"/>
     </type>
-    <text locale="de">"Das Banner wurde auf '$value' geändert."</text>
-    <text locale="en">"Banner has been changed to '$value'."</text>
   </message>
   <message name="newbie_immunity_error" section="events">
     <type>
@@ -3298,8 +2508,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"Eine Partei muß mindestens $int($turns) Wochen alt sein, bevor sie angegriffen oder bestohlen werden kann."</text>
-    <text locale="en">"A faction must be at least $int($turns) weeks old before it can be attacked or stolen from."</text>
   </message>
   <message name="stealeffect" section="events">
     <type>
@@ -3307,47 +2515,35 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) wurden in $region($region) $int($amount) Silberstücke geklaut."</text>
-    <text locale="en">"In $region($region), thieves stole $int($amount) silver from $unit($unit)."</text>
   </message>
   <message name="thiefdiscover" section="events">
     <type>
       <arg name="target" type="unit"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($target) ertappte $unit($unit) beim versuchten Diebstahl."</text>
-    <text locale="en">"$unit($target) caught $unit($unit) in attempted theft."</text>
   </message>
   <message name="stealfatal" section="events">
     <type>
       <arg name="target" type="unit"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) wurde von $unit.dative($target) beim versuchten Diebstahl ertappt."</text>
-    <text locale="en">"$unit($unit) was caught by $unit($target) in attempted theft."</text>
   </message>
   <message name="stealdetect" section="events">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) fühlt sich beobachtet."</text>
-    <text locale="en">"$unit($unit) feels watched."</text>
   </message>
   <message name="stealfail" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) gelang es nicht, sich nahe genug an $unit($target) heranzuschleichen."</text>
-    <text locale="en">"$unit($unit) could not sneak close enough to $unit($target)."</text>
   </message>
   <message name="spyfail" section="events">
     <type>
       <arg name="spy" type="unit"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($spy) gelang es nicht, etwas über $unit($target) herauszufinden."</text>
-    <text locale="en">"$unit($spy) could not find out anything about $unit($target)."</text>
   </message>
   <message name="spyreport" section="events">
     <type>
@@ -3355,8 +2551,6 @@
       <arg name="target" type="unit"/>
       <arg name="status" type="string"/>
     </type>
-    <text locale="de">"$unit($spy) gelang es, Informationen über $unit($target) herauszubekommen: Kampfstatus ${status}."</text>
-    <text locale="en">"$unit($spy) managed to gather information about $unit($target): combat status ${status}."</text>
   </message>
   <message name="spyreport_mage" section="events">
     <type>
@@ -3364,8 +2558,6 @@
       <arg name="target" type="unit"/>
       <arg name="type" type="string"/>
     </type>
-    <text locale="de">"$unit($target) ist ein ${type}-Magier."</text>
-    <text locale="en">"$unit($target) is a ${type}-magician"</text>
   </message>
   <message name="spyreport_skills" section="events">
     <type>
@@ -3373,8 +2565,6 @@
       <arg name="target" type="unit"/>
       <arg name="skills" type="string"/>
     </type>
-    <text locale="de">"$unit($target) beherrscht ${skills}."</text>
-    <text locale="en">"$unit($target) knows ${skills}."</text>
   </message>
   <message name="spyreport_items" section="events">
     <type>
@@ -3382,8 +2572,6 @@
       <arg name="target" type="unit"/>
       <arg name="items" type="items"/>
     </type>
-    <text locale="de">"Im Gepäck von $unit($target) sind $resources($items)."</text>
-    <text locale="en">"$unit($target) carries $resources($items)"</text>
   </message>
   <message name="spyreport_faction" section="events">
     <type>
@@ -3391,16 +2579,12 @@
       <arg name="target" type="unit"/>
       <arg name="faction" type="faction"/>
     </type>
-    <text locale="de">"$unit($target) gehört der Partei $faction($faction) an."</text>
-    <text locale="en">"$unit($target) belongs to $faction($faction)."</text>
   </message>
   <message name="spydetect" section="events">
     <type>
       <arg name="target" type="unit"/>
       <arg name="spy" type="unit"/>
     </type>
-    <text locale="de">"$unit($target) fühlt sich $if($isnull($spy),"","durch $unit($spy) ")beobachtet."</text>
-    <text locale="en">"$unit($target) feels watched$if($isnull($spy),""," by $unit($spy)")."</text>
   </message>
   <message name="donation" section="events">
     <type>
@@ -3408,8 +2592,6 @@
       <arg name="amount" type="int"/>
       <arg name="to" type="faction"/>
     </type>
-    <text locale="de">"$faction($from) gibt ein Almosen von $int($amount) Silber an $faction($to)."</text>
-    <text locale="en">"$faction($from) donates $int($amount) silver to $faction($to)."</text>
   </message>
   <message name="dumbeffect" section="events">
     <type>
@@ -3417,16 +2599,12 @@
       <arg name="weeks" type="int"/>
       <arg name="skill" type="skill"/>
     </type>
-    <text locale="de">"$unit($unit) vergisst durch Dumpfbackenbrot $int($weeks) Wochen des Talentes $skill($skill)."</text>
-    <text locale="en">"$unit($unit) eats a duncebuns and forgets $int($weeks) weeks worth of $skill($skill)."</text>
   </message>
   <message name="malnourish" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) wird durch unzureichende Nahrung geschwächt."</text>
-    <text locale="en">"$unit($unit) is weakened due to malnourishment."</text>
   </message>
   <message name="starvation" section="events">
     <type>
@@ -3435,8 +2613,6 @@
       <arg name="dead" type="int"/>
       <arg name="live" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) verliert in $region($region) $int($dead) von $int($add($live,$dead)) Personen durch Unterernährung."</text>
-    <text locale="en">"$unit($unit) loses $int($dead) of $int($add($live,$dead)) people due to starvation in $region($region)."</text>
   </message>
   <message name="errusingpotion" section="events">
     <type>
@@ -3444,30 +2620,22 @@
       <arg name="command" type="order"/>
       <arg name="using" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit): '$order($command)' - Die Einheit benutzt bereits $resource($using,0)."</text>
-    <text locale="en">"$unit($unit): '$order($command)' - The unit already uses $resource($using,0)."</text>
   </message>
   <message name="peasantluck_success" section="events">
     <type>
       <arg name="births" type="int"/>
     </type>
-    <text locale="de">"$if($eq($births,1),"Einen Bauern","$int($births) Bauern") besucht unverhofft der Storch."</text>
-    <text locale="en">"The stork paid an unexpected visit to $if($eq($births,1),"a peasant","$int($births) peasants")."</text>
   </message>
   <message name="shipsink" section="events">
     <type>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"Die $ship($ship) ist zu stark beschädigt und sinkt."</text>
-    <text locale="en">"The $ship($ship) has suffered too much damage and sinks."</text>
   </message>
   <message name="shipnoshore" section="movement">
     <type>
       <arg name="ship" type="ship"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Die $ship($ship) entdeckt, dass $region($region) Festland ist."</text>
-    <text locale="en">"The $ship($ship) discovers that $region($region) is dry land."</text>
   </message>
   <message name="shipfly" section="movement">
     <type>
@@ -3475,8 +2643,6 @@
       <arg name="from" type="region"/>
       <arg name="to" type="region"/>
     </type>
-    <text locale="de">"Die $ship($ship) fliegt von $region($from) nach $region($to)."</text>
-    <text locale="en">"The $ship($ship) flies from $region($from) to $region($to)."</text>
   </message>
   <message name="shipsail" section="movement">
     <type>
@@ -3484,8 +2650,6 @@
       <arg name="from" type="region"/>
       <arg name="to" type="region"/>
     </type>
-    <text locale="de">"Die $ship($ship) segelt von $region($from) nach $region($to)."</text>
-    <text locale="en">"The $ship($ship) sails from $region($from) to $region($to)."</text>
   </message>
   <message name="storm" section="events">
     <type>
@@ -3493,8 +2657,6 @@
       <arg name="region" type="region"/>
       <arg name="sink" type="int"/>
     </type>
-    <text locale="de">"Die $ship($ship) wird in $region($region) von Stürmen abgetrieben$if($sink," und sinkt","")."</text>
-    <text locale="en">"The $ship($ship) in $region($region) gets off course in heavy storm$if($sink," and sinks","")."</text>
   </message>
   <message name="entermaelstrom" section="events">
     <type>
@@ -3503,24 +2665,18 @@
       <arg name="damage" type="int"/>
       <arg name="sink" type="int"/>
     </type>
-    <text locale="de">"Die $ship($ship) fährt in den Mahlstrom von $region($region) und nimmt $int($damage) Schaden$if($sink," und sinkt","")."</text>
-    <text locale="en">"The $ship($ship) sails into the maelstrom of $region($region) and takes $int($damage) damage$if($sink,". The ship sinks","")."</text>
   </message>
   <message name="forget" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="skill" type="skill"/>
     </type>
-    <text locale="de">"$unit($unit) vergisst $skill($skill)."</text>
-    <text locale="en">"$unit($unit) forgets $skill($skill)."</text>
   </message>
   <message name="givecommand" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="recipient" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) gibt das Kommando an $unit($recipient)."</text>
-    <text locale="en">"$unit($unit) gave control to $unit($recipient)."</text>
   </message>
   <message name="givedumb" section="events">
     <type>
@@ -3528,8 +2684,6 @@
       <arg name="recipient" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) gibt $int($amount) Dumpfbackenbrot an $unit($recipient)."</text>
-    <text locale="en">"$unit($unit) administers $int($amount) duncebuns to $unit($recipient)."</text>
   </message>
   <message name="recruit" section="events">
     <type>
@@ -3538,8 +2692,6 @@
       <arg name="amount" type="int"/>
       <arg name="want" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) rekrutiert $int($amount) von $int($want) Personen."</text>
-    <text locale="en">"$unit($unit) in $region($region) recruits $int($amount) of $int($want) people."</text>
   </message>
   <message name="siege_catapults" section="events">
     <type>
@@ -3547,16 +2699,12 @@
       <arg name="building" type="building"/>
       <arg name="destruction" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) belagert $building($building). Dabei richten die Katapulte Zerstörungen von $int($destruction) Größenpunkten an."</text>
-    <text locale="en">"$building($building) is under siege by $unit($unit). During siege, catapults caused $int($destruction) points destruction."</text>
   </message>
   <message name="siege" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($unit) belagert $building($building)."</text>
-    <text locale="en">"$building($building) is under siege by $unit($unit)."</text>
   </message>
   <message name="drown_on_ship" section="events">
     <type>
@@ -3564,8 +2712,6 @@
       <arg name="ship" type="ship"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) ertrinkt beim Untergang der $ship($ship) in $region($region)."</text>
-    <text locale="en">"$unit($unit) drowns when $ship($ship) in $region($region) sinks."</text>
   </message>
 
   <message name="error320" section="errors">
@@ -3574,10 +2720,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann nicht bewachen, da sie versucht zu fliehen."</text>
-    <text locale="en">"$unit($unit) in $region($region):
-    '$order($command)' - The unit cannot guard the region because it
-    is trying to flee."</text>
   </message>
 
   <message name="error319" section="errors">
@@ -3586,8 +2728,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$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."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot execute this command because it has been in combat."</text>
   </message>
 
   <message name="error318" section="events">
@@ -3596,8 +2736,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Gebäude kann nur einmal pro Runde erweitert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The building can be expanded only once per turn."</text>
   </message>
 
   <message name="error317" section="events">
@@ -3606,8 +2744,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieses Objekt ist unzerstörbar."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This object is indestructible."</text>
   </message>
   <message name="error316" section="events">
     <type>
@@ -3615,8 +2751,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Ohne Zutaten kann ein Alchemist nichts herstellen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Without ingredients an alchemist can not produce anything."</text>
   </message>
   <message name="error315" section="events">
     <type>
@@ -3624,8 +2758,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Nicht alle Zutaten vorhanden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Not all ingredients present."</text>
   </message>
   <message name="error314" section="events">
     <type>
@@ -3633,8 +2765,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Eine Partei kann nur einmal neu starten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Restart can only be used once."</text>
   </message>
   <message name="error313" section="errors">
     <type>
@@ -3642,8 +2772,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Werwesen können nicht arbeiten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Lycantropes don't work."</text>
   </message>
   <message name="error312" section="errors">
     <type>
@@ -3651,8 +2779,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Werwesen können nicht mit anderen Personen gemischt werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Lycantropes may not be mixed with normal people."</text>
   </message>
   <message name="error311" section="errors">
     <type>
@@ -3660,8 +2786,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann sich nicht verwandeln."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit can not change shape."</text>
   </message>
   <message name="error310" section="errors">
     <type>
@@ -3669,8 +2793,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diese Einheit ist kein Werwesen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit is not in lycantropic form."</text>
   </message>
   <message name="error309" section="errors">
     <type>
@@ -3678,8 +2800,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diese Einheit ist schon ein Werwesen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit already assumed lycantropic form."</text>
   </message>
   <message name="error308" section="errors">
     <type>
@@ -3687,8 +2807,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieses Talent kann nicht höher gelernt werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This skill cannot be raised any higher."</text>
   </message>
   <message name="error307" section="errors">
     <type>
@@ -3696,8 +2814,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Snotlinge sind zu dumm, um auf den Feldern zu arbeiten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - We snotlings is too stupid fer dat!"</text>
   </message>
   <message name="error306" section="errors">
     <type>
@@ -3705,8 +2821,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Partei muß mindestens 9 Wochen alt sein, um einen Neustart zu versuchen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Your faction is not old enough to start over."</text>
   </message>
   <message name="error305" section="errors">
     <type>
@@ -3714,8 +2828,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Optionen ZIP und BZIP2 können nur um-, nicht ausgeschaltet werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Options ZIP and BZIP2 can only be switched, not turned off."</text>
   </message>
   <message name="error304" section="errors">
     <type>
@@ -3723,8 +2835,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Einheiten einer Partei, die noch immun gegen Angriffe ist, dürfen nicht bewachen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Units of a faction that can't be attacked may not guard."</text>
   </message>
   <message name="error303" section="errors">
     <type>
@@ -3732,8 +2842,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - In dieser Region kann man nichts verkaufen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No trade is possible in this region."</text>
   </message>
   <message name="error302" section="errors">
     <type>
@@ -3741,8 +2849,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Bereits ein Synonym gesetzt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Synonym already set."</text>
   </message>
   <message name="error301" section="errors">
     <type>
@@ -3750,8 +2856,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Kein Synonym angegeben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Synonym missing."</text>
   </message>
   <message name="error300" section="errors">
     <type>
@@ -3759,8 +2863,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Ungültiges Synonym."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Invalid synonym."</text>
   </message>
   <message name="error299" section="errors">
     <type>
@@ -3768,8 +2870,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Ungültiges Prefix."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Invalid prefix."</text>
   </message>
   <message name="error298" section="errors">
     <type>
@@ -3777,8 +2877,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Magier hat bereits einen Klon."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The magician already has a clone."</text>
   </message>
   <message name="error297" section="errors">
     <type>
@@ -3786,8 +2884,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Gebäude auf dem Ozean können nicht betreten werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Buildings on the ocean may not be entered."</text>
   </message>
   <message name="error296" section="errors">
     <type>
@@ -3795,8 +2891,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier werden niemals Bäume wachsen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Trees won't grow here."</text>
   </message>
   <message name="error295" section="errors">
     <type>
@@ -3804,8 +2898,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Nur ein Magier kann einen Astralkristall benutzen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Only mages may use an astralcrystal."</text>
   </message>
   <message name="error293" section="errors">
     <type>
@@ -3813,7 +2905,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Verbände können nur zwischen Einheiten derselben Partei gebildet werden."</text>
   </message>
   <message name="error291" section="errors">
     <type>
@@ -3821,7 +2912,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist in keinem Verband."</text>
   </message>
   <message name="error290" section="errors">
     <type>
@@ -3829,7 +2919,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Eine Einheit kann nur in einem Verband Mitglied sein."</text>
   </message>
   <message name="error289" section="errors">
     <type>
@@ -3837,8 +2926,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Wie sollen wir uns tarnen?"</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - What should we disguise as?"</text>
   </message>
   <message name="error288" section="errors">
     <type>
@@ -3846,8 +2933,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Wieviel sollen wir einreißen?"</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - How much shall we tear down?"</text>
   </message>
   <message name="error287" section="errors">
     <type>
@@ -3855,8 +2940,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dorthin können wir die Einheit nicht transportieren."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - We cannot transport this unit there."</text>
   </message>
   <message name="error286" section="errors">
     <type>
@@ -3864,8 +2947,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit transportiert uns nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not transporting us."</text>
   </message>
   <message name="error285" section="errors">
     <type>
@@ -3873,8 +2954,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diese Einheit kennt keine Trankrezepte."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit knows no recipes for potions."</text>
   </message>
   <message name="error284" section="errors">
     <type>
@@ -3882,8 +2961,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Nur noch nicht gestärkte Untote können das Ziel dieses Zaubers sein."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Undead can only be affected once by this spell."</text>
   </message>
   <message name="error283" section="events">
     <type>
@@ -3891,8 +2968,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Passwort darf nur Buchstaben und Ziffern enthalten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Your password may only contain alphanumeric symbols."</text>
   </message>
   <message name="error282" section="errors">
     <type>
@@ -3900,8 +2975,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Gegen diese Rasse kann kein Jihad ausgerufen werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot start a jihad against this race."</text>
   </message>
   <message name="error281" section="errors">
     <type>
@@ -3909,8 +2982,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Gegen welche Rasse soll der Jihad ausgerufen werden?"</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - What race did you want the jihad to be against?"</text>
   </message>
   <message name="error280" section="errors">
     <type>
@@ -3918,7 +2989,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dazu muss erst die Spezialeigenschaft erworben werden."</text>
   </message>
   <message name="error278" section="errors">
     <type>
@@ -3926,8 +2996,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Name und Beschreibung des Gebäudes können nicht geändert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot change the name and description of this building."</text>
   </message>
   <message name="error277" section="errors">
     <type>
@@ -3935,8 +3003,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das kann die Einheit nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot do this."</text>
   </message>
   <message name="error276" section="errors">
     <type>
@@ -3944,8 +3010,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier kann man keine Schiffe bauen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Ships cannot be built here."</text>
   </message>
   <message name="error275" section="errors">
     <type>
@@ -3953,8 +3017,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier kann man keine Gebäude errichten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Buildings cannot be built here."</text>
   </message>
   <message name="error274" section="errors">
     <type>
@@ -3962,8 +3024,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann nicht unterrichten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot teach."</text>
   </message>
   <message name="error273" section="errors">
     <type>
@@ -3971,8 +3031,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier kann man nicht unterrichten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot teach here."</text>
   </message>
   <message name="error272" section="errors">
     <type>
@@ -3980,8 +3038,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Pferde müssen leider draußen bleiben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Horses are not allowed inside."</text>
   </message>
   <message name="error271" section="errors">
     <type>
@@ -3989,8 +3045,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier kann man niemanden angreifen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot attack here."</text>
   </message>
   <message name="error270" section="errors">
     <type>
@@ -3998,7 +3052,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier kann man niemanden bestehlen."</text>
   </message>
   <message name="error269" section="errors">
     <type>
@@ -4006,8 +3059,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier kann man nicht zaubern."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot cast spells here."</text>
   </message>
   <message name="error268" section="errors">
     <type>
@@ -4015,8 +3066,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier kann man nichts übergeben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot transfer items here."</text>
   </message>
   <message name="error267" section="errors">
     <type>
@@ -4024,8 +3073,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Nur eine Einzelperson kann das Ticket benutzen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Only a single person can use the ticket."</text>
   </message>
   <message name="error266" section="errors">
     <type>
@@ -4033,8 +3080,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Gegenstand funktioniert nur in der Eingangshalle."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This item only functions in the entry hall."</text>
   </message>
   <message name="error265" section="errors">
     <type>
@@ -4042,8 +3087,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Gegenstand funktioniert nur in der normalen Welt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This item only works in the normal world."</text>
   </message>
   <message name="error264" section="errors">
     <type>
@@ -4051,8 +3094,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieses Gut hat die Einheit nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have this good."</text>
   </message>
   <message name="error263" section="errors">
     <type>
@@ -4060,8 +3101,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieses Gut wird hier produziert."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This good is not produced here."</text>
   </message>
   <message name="error262" section="errors">
     <type>
@@ -4069,8 +3108,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Partei kann keine weiteren Wyrme besitzen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The faction cannot have any more wyrms."</text>
   </message>
   <message name="error261" section="errors">
     <type>
@@ -4078,8 +3115,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Vor den Besitzer eines Schiffes oder Gebäudes kann nicht sortiert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot sort before the owner of a ship or a building."</text>
   </message>
   <message name="error260" section="errors">
     <type>
@@ -4087,8 +3122,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Besitzer eines Schiffes oder Gebäudes kann nicht neu sortiert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The owner of a ship or a building cannot be sorted."</text>
   </message>
   <message name="error259" section="errors">
     <type>
@@ -4096,8 +3129,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Befehl ist nur auf Einheiten innerhalb des selben Gebäudes oder Schiffes anwendbar."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - That order only applies to units in the same building or ship."</text>
   </message>
   <message name="error258" section="errors">
     <type>
@@ -4105,8 +3136,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Zieleinheit ist ungültig."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The target unit is invalid."</text>
   </message>
   <message name="error257" section="errors">
     <type>
@@ -4114,8 +3143,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Ungültiges Locale."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Invalid locale."</text>
   </message>
   <message name="error256" section="errors">
     <type>
@@ -4123,8 +3150,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Um so etwas kann man nicht beten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot pray for this."</text>
   </message>
   <message name="error255" section="errors">
     <type>
@@ -4132,8 +3157,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - So etwas kann man nicht opfern."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot sacrifice this."</text>
   </message>
   <message name="error254" section="errors">
     <type>
@@ -4141,8 +3164,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Auraangabe fehlerhaft oder zuwenig Aura."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Invalid aura specification or not enough aura."</text>
   </message>
   <message name="error253" section="errors">
     <type>
@@ -4150,8 +3171,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Magier ist nicht stark genug, sich den Göttern zu opfern."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This magician is not strong enough to be sacrificed to the gods."</text>
   </message>
   <message name="error252" section="errors">
     <type>
@@ -4159,8 +3178,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Was und wieviel soll geopfert werden?"</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - What and how much should be sacrificed?"</text>
   </message>
   <message name="error251" section="errors">
     <type>
@@ -4168,8 +3185,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diese Kraft können selbst die Götter nicht mehr mächtiger machen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Even the gods cannot improve this power."</text>
   </message>
   <message name="error250" section="errors">
     <type>
@@ -4177,8 +3192,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Nicht genug Karma."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Not enough karma."</text>
   </message>
   <message name="error249" section="errors">
     <type>
@@ -4186,8 +3199,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Schiff kann nicht aufs offene Meer hinaus segeln."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The ship cannot sail into the open seas."</text>
   </message>
   <message name="error248" section="errors">
     <type>
@@ -4195,8 +3206,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Partei muß mindestens 10 Runden alt sein."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The faction has to be 10 turns old."</text>
   </message>
   <message name="error247" section="errors">
     <type>
@@ -4204,8 +3213,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Partei hat schon einen Namen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The faction is already named."</text>
   </message>
   <message name="error246" section="errors">
     <type>
@@ -4213,8 +3220,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Gebäude hat schon einen Namen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The building is already named."</text>
   </message>
   <message name="error245" section="errors">
     <type>
@@ -4222,8 +3227,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Schiff hat schon einen Namen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The ship is already named."</text>
   </message>
   <message name="error244" section="errors">
     <type>
@@ -4231,8 +3234,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat schon einen Namen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is already named."</text>
   </message>
   <message name="error243" section="errors">
     <type>
@@ -4240,8 +3241,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Keine gültige Rasse angegeben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You did not specify a valid race."</text>
   </message>
   <message name="error_onlandonly" section="errors">
     <type>
@@ -4249,8 +3248,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit muß sich an Land befinden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit must be on land."</text>
   </message>
 
   <message name="error_notstonecircle" section="errors">
@@ -4260,8 +3257,6 @@
       <arg name="command" type="order"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $building($building) ist kein Steinkreis."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $building($building) is not a stone circle."</text>
   </message>
 
   <message name="error_notcomplete" section="errors">
@@ -4271,8 +3266,6 @@
       <arg name="command" type="order"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $building($building) muss vor der Weihe fertiggestellt sein."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $building($building) has to be complete before it can be blessed."</text>
   </message>
 
   <message name="error_nograves" section="errors">
@@ -4282,8 +3275,6 @@
       <arg name="command" type="order"/>
       <arg name="target" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - In $region($target) sind keine Gräber."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There are no graves in $region($target)."</text>
   </message>
   <message name="error241" section="errors">
     <type>
@@ -4291,8 +3282,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Partei muß mindestens 81 Wochen alt sein, um einen Neustart mit einer anderen Rasse zu versuchen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The faction must be at least 81 weeks old to restart with a new race."</text>
   </message>
   <message name="error240" section="errors">
     <type>
@@ -4300,8 +3289,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Soll eine Einheit oder ein Schiff verfolgt werden?"</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Is a unit or a ship supposed to be followed?"</text>
   </message>
   <message name="error239" section="errors">
     <type>
@@ -4309,8 +3296,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Soll eine Einheit oder ein Schiff eine neue Nummer bekommen?"</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Is a unit or a ship supposed to get a new number?"</text>
   </message>
   <message name="error238" section="errors">
     <type>
@@ -4318,8 +3303,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier können nur Orks rekrutiert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You can recruit only orcs here."</text>
   </message>
   <message name="error237" section="errors">
     <type>
@@ -4327,8 +3310,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Region befindet sich in Aufruhr."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There are riots in this region."</text>
   </message>
   <message name="error236" section="errors">
     <type>
@@ -4336,8 +3317,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Gebäude ist noch nicht fertig gebaut."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The building is not finished yet."</text>
   </message>
   <message name="error235" section="errors">
     <type>
@@ -4345,8 +3324,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Für das Gebäude wurde noch kein Unterhalt bezahlt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Maintenance has not been paid yet."</text>
   </message>
   <message name="error234" section="errors">
     <type>
@@ -4354,8 +3331,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist mit Ausschiffen beschäftigt.."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is busy disembarking."</text>
   </message>
   <message name="error233" section="errors">
     <type>
@@ -4363,8 +3338,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Typ Einheit kann keine Schiffe betreten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Swimmers cannot enter ships."</text>
   </message>
   <message name="error232" section="errors">
     <type>
@@ -4372,8 +3345,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Typ Einheit kann keine Gebäude betreten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This type of unit cannot enter a building."</text>
   </message>
   <message name="error231" section="errors">
     <type>
@@ -4381,8 +3352,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit oder ihre Tiere würden dort nicht überleben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit or its animals would not survive there."</text>
   </message>
   <message name="error230" section="errors">
     <type>
@@ -4390,8 +3359,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dorthin kann die Einheit uns nicht transportieren."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot transport us to this place."</text>
   </message>
   <message name="entrance_besieged" section="events">
     <type>
@@ -4400,8 +3367,6 @@
       <arg name="command" type="order"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $building($building) wird belagert."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $building($building) is under siege."</text>
   </message>
   <message name="entrance_denied" section="events">
     <type>
@@ -4410,8 +3375,6 @@
       <arg name="command" type="order"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Eintritt in $building($building) wurde verwehrt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Entrance to $building($building) was denied."</text>
   </message>
   <message name="error229" section="errors">
     <type>
@@ -4419,8 +3382,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Ein Vertrauter wird beschworen, verschwindet jedoch wieder, als er keine Verbindung zu seinem Element herstellen kann."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - A familiar is summoned, but it disappears again when it cannot get in contact with its natural element."</text>
   </message>
   <message name="error228" section="errors">
     <type>
@@ -4428,8 +3389,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Nur normale Personen können Steuern eintreiben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Only normal characters can collect taxes."</text>
   </message>
   <message name="error227" section="errors">
     <type>
@@ -4437,8 +3396,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dafür braucht ein Einheit mindestens Kräuterkunde 7."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - A herbalism skill of 7 or higher is required."</text>
   </message>
   <message name="error226" section="errors">
     <type>
@@ -4446,8 +3403,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Einheiten in den hinteren Reihen können nicht angreifen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Units from the backmost rows cannot attack."</text>
   </message>
   <message name="unknown_status" section="errors">
     <type>
@@ -4455,8 +3410,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Unbekannter Kampfstatus."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Unknown combat status."</text>
   </message>
   <message name="unit_unarmed" section="errors">
     <type>
@@ -4464,8 +3417,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht bewaffnet und kampffähig."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not armed and ready to fight."</text>
   </message>
   <message name="one_circle_only" section="events">
     <type>
@@ -4473,8 +3424,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Partei hat bereits ein Magiegebiet."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The faction has already chosen a magical school."</text>
   </message>
   <message name="race_cantwork" section="errors">
     <type>
@@ -4483,8 +3432,6 @@
       <arg name="command" type="order"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) können nicht arbeiten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) cannot work."</text>
   </message>
   <message name="error225" section="errors">
     <type>
@@ -4492,8 +3439,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hungernde Soldaten kämpfen nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Starving units do not fight."</text>
   </message>
   <message name="error224" section="errors">
     <type>
@@ -4501,8 +3446,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hungernde Einheiten können nicht zaubern."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Starving units cannot cast spells."</text>
   </message>
   <message name="error223" section="errors">
     <type>
@@ -4510,8 +3453,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hungernde Einheiten können nicht bewachen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Starving units cannot guard."</text>
   </message>
   <message name="error222" section="errors">
     <type>
@@ -4519,8 +3460,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Zeige alle was?"</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Show all what?"</text>
   </message>
   <message name="error221" section="errors">
     <type>
@@ -4528,8 +3467,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - So etwas kann man hier nicht bauen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot build this here."</text>
   </message>
   <message name="error220" section="errors">
     <type>
@@ -4537,8 +3474,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Im astralen Nebel konnte niemand entdeckt werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No one could be seen in the astral fog."</text>
   </message>
   <message name="gbdream_noteach" section="errors">
     <type>
@@ -4546,8 +3481,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Ein Zauber in dieser Region verhindert das."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There is an active spell in this region that prevents this."</text>
   </message>
   <message name="spell_astral_only" section="errors">
     <type>
@@ -4555,8 +3488,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Zauber kann nur im Astralraum gezaubert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This spell can only be cast on the astral plane."</text>
   </message>
   <message name="error216" section="errors">
     <type>
@@ -4564,8 +3495,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier gibt es keine Verbindung zur astralen Welt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There is no connection to the astral plane here."</text>
   </message>
   <message name="error215" section="errors">
     <type>
@@ -4573,8 +3502,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Von hier aus kann man die astrale Ebene nicht erreichen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot reach the astral plane from here."</text>
   </message>
   <message name="error214" section="errors">
     <type>
@@ -4582,8 +3509,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Einheit ist kein Magier."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Unit is not a magician."</text>
   </message>
   <message name="error213" section="errors">
     <type>
@@ -4591,8 +3516,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Parameter nicht korrekt angegeben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Incorrect parameter."</text>
   </message>
   <message name="error212" section="errors">
     <type>
@@ -4600,8 +3523,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Magier befindet sich nicht auf einem Schiff."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The magician is not on board a ship."</text>
   </message>
   <message name="error211" section="errors">
     <type>
@@ -4609,8 +3530,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Auf dem Schiff liegt bereits so ein Zauber."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The ship is already under this spell."</text>
   </message>
   <message name="error210" section="errors">
     <type>
@@ -4618,8 +3537,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es ist zu gefährlich, ein sturmgepeitschtes Schiff fliegen zu lassen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - It is too dangerous to fly the ship in the storm."</text>
   </message>
   <message name="error209" section="errors">
     <type>
@@ -4627,8 +3544,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Syntax Error."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Syntax Error."</text>
   </message>
   <message name="error208" section="errors">
     <type>
@@ -4636,8 +3551,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Auraangabe fehlerhaft."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Wrong aura values."</text>
   </message>
   <message name="error207" section="errors">
     <type>
@@ -4645,8 +3558,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Zu dieser Einheit kann keine Aura übertragen werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot transfer aura to this unit."</text>
   </message>
   <message name="error206" section="errors">
     <type>
@@ -4654,8 +3565,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Auf dem Gebäude liegt bereits so ein Zauber."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There is alrady a spell on that building."</text>
   </message>
 
   <message name="spellfail_onocean" section="errors">
@@ -4664,8 +3573,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Zauber kann nicht auf hoher See gezaubert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This spell cannot be cast while you are on the ocean."</text>
   </message>
 
   <message name="spellfail_nomonsters" section="errors">
@@ -4674,8 +3581,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Zauber kann nicht auf Monster gezaubert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This spell cannot be cast on monsters."</text>
   </message>
 
   <message name="spellfail_noundead" section="errors">
@@ -4684,8 +3589,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Zauber kann nicht auf Untote  gezaubert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This spell cannot be cast on undead."</text>
   </message>
 
   <message name="spellfail_generous" section="errors">
@@ -4694,8 +3597,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Stimmung in der Region ist so schlecht, dass niemand auf den Zauber reagiert."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The mood in this region is so bad that nobody reacts to the spell."</text>
   </message>
 
   <message name="spellfail_pump" section="errors">
@@ -4706,8 +3607,6 @@
       <arg name="target" type="unit"/>
       <arg name="tregion" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($target) wusste trotz intensivem Verhör nichts über $region($tregion) zu berichten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Despite intense questioning, $unit($target) did not have anything to tell about $region($tregion)."</text>
   </message>
 
   <message name="spellfail_toomanytargets" section="errors">
@@ -4716,8 +3615,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - So viele Persoenen übersteigen die Kräfte des Magiers."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This many people exceed the powers of the magician."</text>
   </message>
 
   <message name="spellfail_noexpensives" section="errors">
@@ -4727,8 +3624,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($target) hat unaufkündbare Bindungen an seine alte Partei."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($target) have unbreakable commitments to their faction."</text>
   </message>
 
   <message name="error205" section="errors">
@@ -4737,8 +3632,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Zauber gelingt nur in einer Ozeanregion."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This spell works only in an ocean region."</text>
   </message>
   <message name="error204" section="errors">
     <type>
@@ -4746,8 +3639,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - In einer Region ohne Bäume kann man diesen Zauber nicht wirken."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot cast this spell in a region without trees."</text>
   </message>
   <message name="error203" section="errors">
     <type>
@@ -4755,8 +3646,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Ziel wurde vergessen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No target has been supplied."</text>
   </message>
   <message name="error202" section="errors">
     <type>
@@ -4764,8 +3653,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das ist keine gültige Rasse."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This is not a valid race."</text>
   </message>
   <message name="error201" section="errors">
     <type>
@@ -4773,8 +3660,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Rasse und Zieleinheit wurden vergessen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Race and target unit have not been supplied."</text>
   </message>
   <message name="error200" section="errors">
     <type>
@@ -4782,8 +3667,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die maximale Aura reicht nicht für diesen Zauber."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Magician's maximum aura is not high enough for this spell."</text>
   </message>
   <message name="error199" section="errors">
     <type>
@@ -4791,8 +3674,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Magier hat bereits einen Vertrauten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The magician already has a familiar."</text>
   </message>
   <message name="error198" section="errors">
     <type>
@@ -4800,8 +3681,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Flammen finden keine Nahrung. Das Feuer erlischt, ohne Schaden anzurichten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The flames find no kindling. The fire dies quickly, causing no damage whatsoever."</text>
   </message>
   <message name="error197" section="errors">
     <type>
@@ -4809,8 +3688,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Um einen Heimstein zu erschaffen, muß der Zauberer in einer Burg sein."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The magician has to be in a castle to create a homestone."</text>
   </message>
   <message name="error196" section="errors">
     <type>
@@ -4818,8 +3695,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das ist keine Waldregion."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This is not a forest region."</text>
   </message>
   <message name="error195" section="errors">
     <type>
@@ -4827,8 +3702,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dorthin führt kein Weg."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There is no route leading there."</text>
   </message>
   <message name="error194" section="errors">
     <type>
@@ -4836,8 +3709,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Zielregion wurde nicht korrekt angegeben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Target region was supplied incorrectly."</text>
   </message>
   <message name="spellfail_astralonly" section="errors">
     <type>
@@ -4845,8 +3716,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Zauber funktioniert nur in der Geisterwelt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This spell will only work in the realm of spirits."</text>
   </message>
   <message name="spellfail_astralblock" section="errors">
     <type>
@@ -4854,8 +3723,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Wege zwischen Geisterwelt und Realität scheinen blockiert zu sein."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The paths to the spirit world seem to be blocked."</text>
   </message>
   <message name="error191" section="errors">
     <type>
@@ -4863,8 +3730,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Zauber funktioniert nur in Wäldern."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This spell works only in forests."</text>
   </message>
   <message name="error190" section="errors">
     <type>
@@ -4872,8 +3737,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Zauber funktioniert nur in der materiellen Welt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This spell works only in the material world."</text>
   </message>
   <message name="error189" section="errors">
     <type>
@@ -4881,8 +3744,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Selbst der mächtigste Magier der Welt könnte keinen Ozean austrocknen lassen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Even the gods cannot dry out an entire ocean."</text>
   </message>
   <message name="error188" section="errors">
     <type>
@@ -4890,8 +3751,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Zauber kann nicht im Sumpf gezaubert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot cast this spell in a swamp."</text>
   </message>
   <message name="error186" section="errors">
     <type>
@@ -4899,8 +3758,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Zauber kann nur auf Land gelegt werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This spell only works on dry land."</text>
   </message>
   <message name="error185" section="errors">
     <type>
@@ -4908,8 +3765,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Zauber scheint ungewöhnlich schwach zu sein. Irgendetwas hat die magischen Energien abgeleitet."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The spell seems exceptionally weak. Something has interfred with the magical energies."</text>
   </message>
   <message name="error187" section="errors">
     <type>
@@ -4917,8 +3772,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann den Befehl in dieser Runde nicht ausführen, da sie sich bewegt hat."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot execute this command because it has moved."</text>
   </message>
   <message name="error184" section="errors">
     <type>
@@ -4926,8 +3779,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit bewegt sich nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not move."</text>
   </message>
   <message name="error183" section="errors">
     <type>
@@ -4935,8 +3786,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Magier befindet sich nicht auf einem Schiff."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The magician is not on board a ship."</text>
   </message>
   <message name="error182" section="errors">
     <type>
@@ -4944,8 +3793,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Schiff kann in diese Richtung nicht ablegen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The ship cannot leave in this direction."</text>
   </message>
   <message name="error181" section="errors">
     <type>
@@ -4953,8 +3800,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dazu muß sich der Magier in der Burg oder an Bord des Schiffes befinden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - To do this, the magician has to be in a castle or on board a ship."</text>
   </message>
   <message name="error180" section="errors">
     <type>
@@ -4962,8 +3807,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Zauber schlägt fehl."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The spell fails."</text>
   </message>
   <message name="error179" section="errors">
     <type>
@@ -4971,8 +3814,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieses Magiegebiet kann die Einheit nicht lernen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot learn this magic sphere."</text>
   </message>
   <message name="error178" section="errors">
     <type>
@@ -4980,8 +3821,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es wurde kein Magiegebiet angegeben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No magic sphere was supplied."</text>
   </message>
   <message name="error177" section="errors">
     <type>
@@ -4989,8 +3828,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diesen Spruch kann der Vertraute nicht zaubern."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The familiar cannot cast this spell."</text>
   </message>
   <message name="error176" section="errors">
     <type>
@@ -4998,8 +3835,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diesen Spruch kann man nicht in die Ferne richten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot cast this spell on a distant target."</text>
   </message>
   <message name="error175" section="errors">
     <type>
@@ -5007,8 +3842,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diesen Spruch kann man nicht auf einem sich bewegenden Schiff stehend zaubern."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot cast this spell while standing on a moving ship."</text>
   </message>
   <message name="error174" section="errors">
     <type>
@@ -5016,8 +3849,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Zauber ist nur im Kampf sinnvoll."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This spell only makes sense in combat."</text>
   </message>
   <message name="error173" section="errors">
     <type>
@@ -5025,8 +3856,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Selbst in der Bibliothek von Xontormia konnte dieser Spruch nicht gefunden werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Even in the Xontormia Library, this spell could not be found."</text>
   </message>
   <message name="error172" section="errors">
     <type>
@@ -5034,8 +3863,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es wurde kein Zauber angegeben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There was no spell supplied."</text>
   </message>
   <message name="error171" section="errors">
     <type>
@@ -5043,8 +3870,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diesen Kampfzauber gibt es nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This combat spell does not exist."</text>
   </message>
   <message name="error170" section="errors">
     <type>
@@ -5052,8 +3877,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Bauern nehmen dieses großzügige Geschenk nicht an."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The peasants did not accept this gracious gift."</text>
   </message>
   <message name="error169" section="errors">
     <type>
@@ -5061,8 +3884,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diesen Zauber kennt die Einheit nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not know this spell."</text>
   </message>
   <message name="error168" section="errors">
     <type>
@@ -5070,8 +3891,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es konnten keine Luxusgüter verkauft werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No luxury items could be sold."</text>
   </message>
   <message name="error167" section="errors">
     <type>
@@ -5079,8 +3898,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit geht nicht zu den Bauern."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not go to the peasants."</text>
   </message>
   <message name="error166" section="errors">
     <type>
@@ -5088,8 +3905,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diese Rasse kann eine Burg nicht belagern."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This race cannot besiege a castle."</text>
   </message>
   <message name="error165" section="errors">
     <type>
@@ -5097,8 +3912,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Trank bekommt der Einheit nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The potion does not agree with the unit."</text>
   </message>
   <message name="error163" section="errors">
     <type>
@@ -5106,8 +3919,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Nestwärme kann nur von Insektenvölkern benutzt werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This potion can only be used by insects."</text>
   </message>
   <message name="error162" section="errors">
     <type>
@@ -5115,8 +3926,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Heiltrank wird automatisch bei Bedarf benutzt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This healing potion will be automatically used when needed."</text>
   </message>
   <message name="error161" section="errors">
     <type>
@@ -5124,8 +3933,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit besitzt den Trank nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have this potion."</text>
   </message>
   <message name="error160" section="errors">
     <type>
@@ -5133,8 +3940,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es konnten keine Luxusgüter gekauft werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No luxury items could be bought."</text>
   </message>
   <message name="error159" section="errors">
     <type>
@@ -5142,8 +3947,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es konnten keine Personen übergeben werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No person could be handed over."</text>
   </message>
   <message name="error158" section="errors">
     <type>
@@ -5151,8 +3954,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Magier arbeiten grundsätzlich nur alleine!"</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Magicians always work alone!"</text>
   </message>
   <message name="error157" section="errors">
     <type>
@@ -5160,8 +3961,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Partei hat ein anderes Magiegebiet."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The faction has a different magic sphere."</text>
   </message>
   <message name="error156" section="errors">
     <type>
@@ -5169,8 +3968,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Zuviele Alchemisten in der Partei."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Too many alchemists in the faction."</text>
   </message>
   <message name="error155" section="errors">
     <type>
@@ -5178,8 +3975,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Zuviele Magier in der Partei."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Too many magicians in the faction."</text>
   </message>
   <message name="error154" section="errors">
     <type>
@@ -5187,8 +3982,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hochqualifizierte Personen weigern sich, für andere Parteien zu arbeiten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Highly qualified people refuse to work for other parties."</text>
   </message>
   <message name="error153" section="errors">
     <type>
@@ -5196,8 +3989,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit schließt sich den Bauern an."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit joins the local peasants."</text>
   </message>
   <message name="error152" section="errors">
     <type>
@@ -5205,8 +3996,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit springt über Bord und ertrinkt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit jumps over board and drowns."</text>
   </message>
   <message name="error69" section="errors">
     <type>
@@ -5214,8 +4003,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Region wird bewacht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The region is guarded."</text>
   </message>
   <message name="error135" section="errors">
     <type>
@@ -5223,8 +4010,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Unbekannte Option."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Unknown option."</text>
   </message>
   <message name="error60" section="errors">
     <type>
@@ -5232,8 +4017,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit wird belagert."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is under siege."</text>
   </message>
   <message name="error151" section="errors">
     <type>
@@ -5241,8 +4024,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Zum Straßenbau braucht man Steine."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You need stones to build a road."</text>
   </message>
   <message name="error149" section="errors">
     <type>
@@ -5250,8 +4031,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Wohin soll die Botschaft gehen?"</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Who is supposed to get this message?"</text>
   </message>
   <message name="error148" section="errors">
     <type>
@@ -5259,8 +4038,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht der Burgherr."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not in command of a castle."</text>
   </message>
   <message name="error147" section="errors">
     <type>
@@ -5268,8 +4045,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht Burgherr der größten Burg in der Region."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not in command of the largest castle in the region."</text>
   </message>
   <message name="error146" section="errors">
     <type>
@@ -5277,8 +4052,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht der Kapitän des Schiffes."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not captain of a ship."</text>
   </message>
   <message name="error145" section="errors">
     <type>
@@ -5286,8 +4059,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist in keiner Burg."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not in a castle."</text>
   </message>
   <message name="error144" section="errors">
     <type>
@@ -5295,8 +4066,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist auf keinem Schiff."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not on board a ship."</text>
   </message>
   <message name="error143" section="errors">
     <type>
@@ -5304,8 +4073,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist auf einem Schiff."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is on board a ship."</text>
   </message>
   <message name="error142" section="errors">
     <type>
@@ -5313,8 +4080,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat zuwenig Silber, um zu rekrutieren."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have enough silver for recruiting."</text>
   </message>
   <message name="error141" section="errors">
     <type>
@@ -5322,8 +4087,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat nicht mehr genug Kristalle für so viele Personen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have enough crystals left for this many people."</text>
   </message>
   <message name="error140" section="errors">
     <type>
@@ -5331,8 +4094,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit befindet sich weder in einer Burg noch auf einem Schiff."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is neither in a castle nor on board a ship."</text>
   </message>
   <message name="error139" section="errors">
     <type>
@@ -5340,8 +4101,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Unterschiedliche Typen können nicht gemischt werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Different types do not mix."</text>
   </message>
   <message name="error138" section="errors">
     <type>
@@ -5349,8 +4108,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Uns gehört nichts, was man abreißen oder versenken könnte."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - We do not have anything that could be demolished."</text>
   </message>
   <message name="error137" section="errors">
     <type>
@@ -5358,8 +4115,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Unbekannter Hilfe-Modus."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Unknown help mode."</text>
   </message>
   <message name="error134" section="errors">
     <type>
@@ -5367,8 +4122,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Unbekannte Meldungs-Option."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Unknown report option."</text>
   </message>
   <message name="error133" section="errors">
     <type>
@@ -5376,8 +4129,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Um in Wüsten Straßen bauen zu können, muß zuerst eine Karawanserei errichtet werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You must build a caravansary before building roads through deserts."</text>
   </message>
   <message name="error132" section="errors">
     <type>
@@ -5385,8 +4136,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Um in Sümpfen Straßen bauen zu können, muß zuerst ein Damm errichtet werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You must build a dam before building roads through swamps."</text>
   </message>
   <message name="error129" section="errors">
     <type>
@@ -5394,8 +4143,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - So viele Leute kann die Partei nicht aufnehmen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The faction cannot hire so many people."</text>
   </message>
   <message name="error128" section="errors">
     <type>
@@ -5403,8 +4150,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - So viele Fremde kann die Partei nicht aufnehmen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The faction cannot hire so many strangers."</text>
   </message>
   <message name="error127" section="errors">
     <type>
@@ -5412,8 +4157,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - So viele Fremde kann Deine Partei nicht aufnehmen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Your faction cannot hire so many strangers."</text>
   </message>
   <message name="error126" section="errors">
     <type>
@@ -5421,8 +4164,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - So etwas kann man nicht verkaufen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot sell this."</text>
   </message>
   <message name="error_cannotmake" section="errors">
     <type>
@@ -5430,8 +4171,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - So etwas kann man nicht machen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot produce this."</text>
   </message>
   <message name="error124" section="errors">
     <type>
@@ -5439,8 +4178,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - So etwas kann man nicht auf dem Markt kaufen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot buy that on a market place."</text>
   </message>
   <message name="error123" section="errors">
     <type>
@@ -5448,8 +4185,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - So etwas hat die Einheit nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have such a thing."</text>
   </message>
   <message name="error122" section="errors">
     <type>
@@ -5457,8 +4192,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Pferde kann man nur in einer Pferdezucht züchten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You can only breed horses in a stable."</text>
   </message>
   <message name="error121" section="errors">
     <type>
@@ -5466,8 +4199,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - So etwas gibt es hier nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - That resource does not exist in this region."</text>
   </message>
   <message name="error120" section="errors">
     <type>
@@ -5475,8 +4206,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Personen können nur an Menschen übergeben werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Characters can be given only to human parties."</text>
   </message>
   <message name="error119" section="errors">
     <type>
@@ -5484,8 +4213,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Ohne einen Handelsposten gibt es keinen Markt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There is no marketplace without at least a tradepost."</text>
   </message>
   <message name="error118" section="errors">
     <type>
@@ -5493,8 +4220,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diesen Gegenstand kann die Einheit nicht herstellen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit cannot produce that."</text>
   </message>
   <message name="error117" section="errors">
     <type>
@@ -5502,8 +4227,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diese Rasse kann das nicht herstellen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This race cannot produce that."</text>
   </message>
   <message name="error116" section="errors">
     <type>
@@ -5511,8 +4234,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Nummer kann nicht vergeben werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Number can not be assigned."</text>
   </message>
   <message name="error115" section="errors">
     <type>
@@ -5520,8 +4241,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Nummer ist schon belegt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Number is already in use."</text>
   </message>
   <message name="error114" section="errors">
     <type>
@@ -5529,8 +4248,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Nummer ist nicht im gültigen Bereich."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Number is not valid."</text>
   </message>
   <message name="error113" section="errors">
     <type>
@@ -5538,8 +4255,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Nichts angegeben, was wir übergeben sollen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Item to be handed over was not supplied."</text>
   </message>
   <message name="error112" section="errors">
     <type>
@@ -5547,8 +4262,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Namen dürfen keine Klammern enthalten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Names may not contain parenthesis."</text>
   </message>
   <message name="error111" section="errors">
     <type>
@@ -5556,8 +4269,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Nachricht zu lang - gekürzt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Message has been cut (too long)."</text>
   </message>
   <message name="error110" section="errors">
     <type>
@@ -5565,8 +4276,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Man muß angeben, ob eine Burg, ein Schiff, eine Region oder eine Einheit beschrieben werden soll."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Specify if description is for a castle, a ship, a region, or a unit."</text>
   </message>
   <message name="error109" section="errors">
     <type>
@@ -5574,8 +4283,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Man muß angeben, ob eine Burg, ein Schiff, eine Einheit, eine Region oder eine Partei benannt werden soll."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Specify if a castle, a ship, a region, or a unit is supposed to be named."</text>
   </message>
   <message name="error108" section="errors">
     <type>
@@ -5583,8 +4290,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es sind keine Kräuter zu finden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No herbs could be found."</text>
   </message>
   <message name="error107" section="errors">
     <type>
@@ -5592,8 +4297,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Man braucht mindestens zwei Pferde, um sie zu züchten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You need at least two horses to breed more."</text>
   </message>
   <message name="error106" section="errors">
     <type>
@@ -5601,8 +4304,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Magier müssen zum studieren allein sein."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - When studying, magicians need to be alone."</text>
   </message>
   <message name="error105" section="errors">
     <type>
@@ -5610,8 +4311,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Leere Einheiten können nicht übergeben werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Empty units can not be handed over."</text>
   </message>
   <message name="error104" section="errors">
     <type>
@@ -5619,8 +4318,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieses Metall kann nur in einem Bergwerk abgebaut werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This metal can be excavated only in a mine."</text>
   </message>
   <message name="error103" section="errors">
     <type>
@@ -5628,8 +4325,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Keiner hier kann Straßen bauen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Nobody here can build roads."</text>
   </message>
   <message name="error102" section="errors">
     <type>
@@ -5637,8 +4332,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann keine weiteren Güter handeln."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot trade any more goods."</text>
   </message>
   <message name="error101" section="errors">
     <type>
@@ -5646,8 +4339,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Keiner hier kann ein Gebäude errichten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Nobody here can construct a building."</text>
   </message>
   <message name="error100" section="errors">
     <type>
@@ -5655,8 +4346,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Keiner hier ist gelernter Schiffbauer."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Nobody here is a skilled ship builder."</text>
   </message>
   <message name="error99" section="errors">
     <type>
@@ -5664,8 +4353,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit will nicht transportiert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not want to be transported."</text>
   </message>
   <message name="error98" section="errors">
     <type>
@@ -5673,8 +4360,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Insekten können im Winter nur in Wüsten rekrutiert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - In winter, insects can be recruited only in deserts."</text>
   </message>
   <message name="error97" section="errors">
     <type>
@@ -5682,8 +4367,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - In Gletschern können keine Insekten rekrutiert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Insects cannot be recruited in glacier regions."</text>
   </message>
   <message name="error96" section="errors">
     <type>
@@ -5691,8 +4374,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - In dieser Einheit gibt es niemanden, den man transferieren könnte."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Nobody in this unit can be transferred."</text>
   </message>
   <message name="error95" section="errors">
     <type>
@@ -5700,8 +4381,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Illusionen können eine Region nicht bewachen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Illusions cannot guard a region."</text>
   </message>
   <message name="error94" section="errors">
     <type>
@@ -5709,8 +4388,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier kann man keine Straße bauen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot build a road here."</text>
   </message>
   <message name="error93" section="errors">
     <type>
@@ -5718,8 +4395,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier gibt es schon einen Hafen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There is already a port in this region."</text>
   </message>
   <message name="error_nopeasants" section="errors">
     <type>
@@ -5727,8 +4402,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier gibt es keine Bauern."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There are no peasants in this region."</text>
   </message>
   <message name="error92" section="errors">
     <type>
@@ -5736,8 +4409,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier gibt es keinen normalen Wald."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There is no normal forest in this region."</text>
   </message>
   <message name="error91" section="errors">
     <type>
@@ -5745,8 +4416,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Hier gibt es keine Mallornbäume."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There are no mallorn trees here."</text>
   </message>
   <message name="error90" section="errors">
     <type>
@@ -5754,8 +4423,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit fährt nicht mit uns."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have travel with us."</text>
   </message>
   <message name="error89" section="errors">
     <type>
@@ -5763,8 +4430,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Geldgebot fehlt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Money offer is missing."</text>
   </message>
   <message name="error88" section="errors">
     <type>
@@ -5772,8 +4437,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat nicht genügend Materialien für den Schiffbau."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is lacking materials for building the ship."</text>
   </message>
   <message name="error87" section="errors">
     <type>
@@ -5781,8 +4444,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Für das Elixier benötigt man Drachenblut."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Dragon blood is required for this elixir."</text>
   </message>
   <message name="error86" section="errors">
     <type>
@@ -5790,8 +4451,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Falsches Passwort."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Wrong password."</text>
   </message>
   <message name="error85" section="errors">
     <type>
@@ -5799,8 +4458,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es wurde keine Emailadresse angegeben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No email address was supplied."</text>
   </message>
   <message name="error84" section="errors">
     <type>
@@ -5808,8 +4465,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es wurde kein Name angegeben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No name was supplied."</text>
   </message>
   <message name="error83" section="errors">
     <type>
@@ -5817,8 +4472,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es konnte kein Bauer gefangen werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No peasant could be caught."</text>
   </message>
   <message name="error82" section="errors">
     <type>
@@ -5826,8 +4479,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es gibt keine Abstimmung mit dieser Nummer."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There is no agreement with this number."</text>
   </message>
   <message name="error81" section="errors">
     <type>
@@ -5835,8 +4486,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Einheit muß zuerst die Region bewachen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit must first guard the region."</text>
   </message>
   <message name="error80" section="errors">
     <type>
@@ -5844,8 +4493,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Einheit ist nicht bewaffnet und kampffähig."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not armed and ready to fight."</text>
   </message>
   <message name="error79" section="errors">
     <type>
@@ -5853,8 +4500,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Ein Schiff oder eine Burg muß angegeben werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - A ship or a castle must be supplied."</text>
   </message>
   <message name="error78" section="errors">
     <type>
@@ -5862,8 +4507,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Ein Fluch verhindert die Übergabe."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - A curse prevented the transfer from happening."</text>
   </message>
   <message name="error77" section="errors">
     <type>
@@ -5871,8 +4514,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieses Talent wurde nicht erkannt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The skill could not be recognized."</text>
   </message>
   <message name="error771" section="errors">
     <type>
@@ -5880,8 +4521,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieses Talent kann die Einheit nicht lernen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot learn this skill."</text>
   </message>
   <message name="error76" section="errors">
     <type>
@@ -5889,8 +4528,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diesen Gegenstand kann man nicht benutzen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This item cannot be used."</text>
   </message>
   <message name="error75" section="errors">
     <type>
@@ -5898,8 +4535,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit nimmt niemanden an."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit does not accept anybody."</text>
   </message>
   <message name="error73" section="errors">
     <type>
@@ -5907,8 +4542,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Eine hungernde Einheit kann niemanden weggeben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Hungry units cannot give anybody away."</text>
   </message>
   <message name="error74" section="errors">
     <type>
@@ -5916,8 +4549,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diese Einheit kann niemanden weggeben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit cannot give anybody away."</text>
   </message>
 
   <message name="feedback_no_contact" section="errors">
@@ -5927,8 +4558,6 @@
       <arg name="command" type="order"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($target) hat keinen Kontakt mit uns aufgenommen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($target) did not contact us."</text>
   </message>
 
   <message name="feedback_no_astralregion" section="errors">
@@ -5937,8 +4566,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es kann hier kein Kontakt zur Astralwelt aufgenommen werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There is no connection to the astral plane here."</text>
   </message>
 
   <message name="feedback_no_contact_resist" section="errors">
@@ -5948,8 +4575,6 @@
       <arg name="command" type="order"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($target) hat keinen Kontakt mit uns aufgenommen und widersteht dem Zauber."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($target) did not contact us, and resists the spell."</text>
   </message>
   <message name="feedback_no_contact_no_resist" section="errors">
     <type>
@@ -5958,8 +4583,6 @@
       <arg name="command" type="order"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($target) hat keinen Kontakt mit uns aufgenommen, aber widersteht dem Zauber nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($target) did not contact us, but cannot resist the spell."</text>
   </message>
   <message name="error71" section="errors">
     <type>
@@ -5967,8 +4590,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Richtung wurde nicht erkannt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The given direction was not recognized."</text>
   </message>
   <message name="unknowndirection" section="errors">
     <type>
@@ -5977,8 +4598,6 @@
       <arg name="command" type="order"/>
       <arg name="dirname" type="string"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Richtung '$dirname' wurde nicht erkannt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Direction '$dirname' was not recognized."</text>
   </message>
   <message name="error70" section="errors">
     <type>
@@ -5986,8 +4605,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Region wird von Nichtalliierten bewacht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This region is guarded by a non-allied faction."</text>
   </message>
   <message name="region_guarded" section="errors">
     <type>
@@ -5996,8 +4613,6 @@
       <arg name="command" type="order"/>
       <arg name="guard" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Region wird von $unit($guard), einer nichtalliierten Einheit, bewacht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This region is guarded by $unit($guard), a non-allied unit."</text>
   </message>
   <message name="error67" section="errors">
     <type>
@@ -6005,8 +4620,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Pferde würden ertrinken."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The horses would drown."</text>
   </message>
   <message name="error66" section="errors">
     <type>
@@ -6014,8 +4627,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Partei wurde nicht gefunden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The faction could not be found."</text>
   </message>
   <message name="error65" section="errors">
     <type>
@@ -6023,8 +4634,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Lernkosten können nicht bezahlt werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Tuition was too high to be paid."</text>
   </message>
   <message name="use_realworld_only" section="errors">
     <type>
@@ -6032,8 +4641,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Gegenstand kann nur in der realen Welt benutzt werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This object can only be used in the real world."</text>
   </message>
   <message name="error64" section="errors">
     <type>
@@ -6041,8 +4648,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) ist nicht ausreichend getarnt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($unit) is not sufficiently stealthy."</text>
   </message>
   <message name="feedback_unit_not_found" section="errors">
     <type>
@@ -6050,8 +4655,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit wurde nicht gefunden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit could not be found."</text>
   </message>
 
   <message name="feedback_give_forbidden" section="errors">
@@ -6060,8 +4663,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Einheit kann nichts gegeben werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot give anything to this unit."</text>
   </message>
 
   <message name="pump_effect" section="events">
@@ -6070,8 +4671,6 @@
       <arg name="unit" type="unit"/>
       <arg name="tregion" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) horcht $unit($unit) über $region($tregion) aus."</text>
-    <text locale="en">"$unit($mage) questions $unit($unit) about $region($tregion)."</text>
   </message>
 
   <message name="headache_effect_0" section="events">
@@ -6079,16 +4678,12 @@
       <arg name="mage" type="unit"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) verschafft $unit($unit) einige feuchtfröhliche Stunden mit heftigen Nachwirkungen."</text>
-    <text locale="en">"$unit($mage) invites $unit($unit) for a few too many drinks and a massive hangover."</text>
   </message>
 
   <message name="headache_effect_1" section="events">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) hat höllische Kopfschmerzen und kann sich an die vergangene Woche nicht mehr erinnern. Nur noch daran, wie alles mit einer fröhlichen Feier in irgendeiner Taverne anfing...."</text>
-    <text locale="en">"$unit($unit) has a splitting headache and can hardly remember last week. Except that it all started in the tavern..."</text>
   </message>
 
   <message name="calm_effect" section="events">
@@ -6096,16 +4691,12 @@
       <arg name="mage" type="unit"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) besänftigt $unit($unit)."</text>
-    <text locale="en">"$unit($mage) calms $unit($unit)."</text>
   </message>
 
   <message name="seduce_effect_1" section="events">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) verfiel dem Glücksspiel und hat fast sein ganzes Hab und gut verspielt."</text>
-    <text locale="en">"$unit($unit) gambles for high stakes and loses almost everything."</text>
   </message>
 
   <message name="seduce_effect_0" section="events">
@@ -6114,8 +4705,6 @@
       <arg name="mage" type="unit"/>
       <arg name="items" type="items"/>
     </type>
-    <text locale="de">"$unit($unit) schenkt $unit($mage) $resources($items)."</text>
-    <text locale="en">"$unit($unit) gives $unit($mage) $resources($items)."</text>
   </message>
 
   <message name="shapeshift_effect" section="events">
@@ -6124,16 +4713,12 @@
       <arg name="target" type="unit"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($mage) läßt $unit($target) als $race($race,$unit.size($target)) erscheinen."</text>
-    <text locale="en">"$unit($mage) makes $unit($target) appear as $race($race,$unit.size($target))."</text>
   </message>
 
   <message name="magicresistance_effect" section="events">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) wird kurz von einem magischen Licht umhüllt."</text>
-    <text locale="en">"$unit($unit) is briefly surrounded by a magical light."</text>
   </message>
   <message name="stormwinds_reduced" section="events">
     <type>
@@ -6141,15 +4726,11 @@
       <arg name="ships" type="int"/>
       <arg name="maxships" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) konnte nur $int($ships) von $int($maxships) Schiffen verzaubern."</text>
-    <text locale="en">"$unit($unit) could only enchant $int($ships) of $int($maxships) ships."</text>
   </message>
   <message name="stormwinds_effect" section="events">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) beschwört einen magischen Wind, der die Schiffe über das Wasser treibt."</text>
-    <text locale="en">"$unit($unit) calls up a magical storm that whips the ship over the waters."</text>
   </message>
   <message name="error59" section="errors">
     <type>
@@ -6157,8 +4738,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit weiß nichts über Botanik."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not know anything about herbalism."</text>
   </message>
   <message name="error58" section="errors">
     <type>
@@ -6166,8 +4745,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit weiß nicht, wie man gaukelt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not know how to entertain."</text>
   </message>
   <message name="error57" section="errors">
     <type>
@@ -6175,8 +4752,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit trägt zuviel Gewicht, um sich bewegen zu können."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is too heavily loaded to move."</text>
   </message>
   <message name="error56" section="errors">
     <type>
@@ -6184,8 +4759,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann soviele Pferde nicht bändigen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot tame that many horses."</text>
   </message>
   <message name="error55" section="errors">
     <type>
@@ -6193,8 +4766,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann sich nicht fortbewegen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot move."</text>
   </message>
   <message name="error54" section="errors">
     <type>
@@ -6202,8 +4773,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann nicht handeln."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot trade."</text>
   </message>
   <message name="error53" section="errors">
     <type>
@@ -6211,8 +4780,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann keine Tränke herstellen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot make potions."</text>
   </message>
   <message name="error52" section="errors">
     <type>
@@ -6220,8 +4787,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann keine weiteren langen Befehle ausführen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot execute more long orders."</text>
   </message>
   <message name="error51" section="errors">
     <type>
@@ -6229,8 +4794,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat nicht genug Silber."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have enough silver."</text>
   </message>
   <message name="error50" section="errors">
     <type>
@@ -6238,8 +4801,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht erfahren genug dafür."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not experienced enough to do this."</text>
   </message>
   <message name="error49" section="errors">
     <type>
@@ -6247,8 +4808,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht der Eigentümer."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not the owner."</text>
   </message>
   <message name="error_no_tax_skill" section="errors">
     <type>
@@ -6256,8 +4815,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht geschult im Eintreiben von Steuern."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not now how to tax."</text>
   </message>
 
   <message name="error48" section="errors">
@@ -6266,8 +4823,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist nicht bewaffnet und kampffähig."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not armed and ready to fight."</text>
   </message>
   <message name="error47" section="errors">
     <type>
@@ -6275,8 +4830,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist mit uns alliiert."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit is one of our allies."</text>
   </message>
   <message name="error46" section="errors">
     <type>
@@ -6284,8 +4837,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist in keiner Taverne."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not in a tavern."</text>
   </message>
   <message name="error45" section="errors">
     <type>
@@ -6293,8 +4844,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist eine der unsrigen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit is one of our own."</text>
   </message>
   <message name="error44" section="errors">
     <type>
@@ -6302,8 +4851,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist auf hoher See."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is off shore."</text>
   </message>
   <message name="error43" section="errors">
     <type>
@@ -6311,8 +4858,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat so etwas nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have this."</text>
   </message>
   <message name="error42" section="errors">
     <type>
@@ -6320,8 +4865,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat nicht genug Wagenlenker oder zuviel andere Fracht, um die Wagen aufzuladen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have enough coachmen or has too much freights to lad the wagons."</text>
   </message>
   <message name="error41" section="errors">
     <type>
@@ -6329,8 +4872,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat nicht genug Silber."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have enough silver."</text>
   </message>
   <message name="error40" section="errors">
     <type>
@@ -6338,8 +4879,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat keinen Kontakt mit uns aufgenommen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit did not contact us."</text>
   </message>
   <message name="error39" section="errors">
     <type>
@@ -6347,8 +4886,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat keine Spionage gelernt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit has not yet learned espionage."</text>
   </message>
   <message name="error38" section="errors">
     <type>
@@ -6356,8 +4893,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat keine Kräuter."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have any herbs."</text>
   </message>
   <message name="error37" section="errors">
     <type>
@@ -6365,8 +4900,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat diesen Trank nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have this potion."</text>
   </message>
   <message name="error36" section="errors">
     <type>
@@ -6374,8 +4907,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat diesen Gegenstand nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have this item."</text>
   </message>
   <message name="nogive_reserved" section="errors">
     <type>
@@ -6385,8 +4916,6 @@
       <arg name="reservation" type="int"/>
       <arg name="resource" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat diesen Gegenstand zwar, aber sämtliche $int($reservation) $resource($resource,$reservation) sind reserviert."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit has this item, but all $int($reservation) $resource($resource,$reservation) are reserved."</text>
   </message>
   <message name="error35" section="errors">
     <type>
@@ -6394,8 +4923,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat diese Kräuter nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit does not have these herbs."</text>
   </message>
   <message name="error_unit_size" section="errors">
     <type>
@@ -6404,8 +4931,6 @@
       <arg name="command" type="order"/>
       <arg name="maxsize" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Einheiten dürfen nicht mehr als $int($maxsize) Personen enthalten."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Units may not have more than $int($maxsize) members."</text>
   </message>
   <message name="enter_overload" section="errors">
     <type>
@@ -6413,8 +4938,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit darf nicht an Bord kommen, da sie das Schiff überladen würde."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit cannot go aboard, the ship would be overloaded."</text>
   </message>
   <message name="error34" section="errors">
     <type>
@@ -6422,8 +4945,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit darf nicht an Bord kommen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit has no permission to come on board."</text>
   </message>
   <message name="error33" section="errors">
     <type>
@@ -6431,8 +4952,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit befindet sich nicht in unserer Burg."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not in our castle."</text>
   </message>
   <message name="error32" section="errors">
     <type>
@@ -6440,8 +4959,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit befindet sich nicht an Bord unseres Schiffes."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit is not on board our ship."</text>
   </message>
   <message name="error31" section="errors">
     <type>
@@ -6449,8 +4966,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Burg wurde nicht gefunden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The castle could not be found."</text>
   </message>
   <message name="error30" section="errors">
     <type>
@@ -6458,8 +4973,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Botschaft enthält keinen Text."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The message does not contain text."</text>
   </message>
   <message name="error28" section="errors">
     <type>
@@ -6467,8 +4980,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Bauern sind schlecht gelaunt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The peasant morale is low."</text>
   </message>
   <message name="error27" section="errors">
     <type>
@@ -6476,8 +4987,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Anzahl zu verkaufender Produkte fehlt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The amount of items for sale is missing."</text>
   </message>
   <message name="error26" section="errors">
     <type>
@@ -6485,8 +4994,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Anzahl zu kaufender Produkte fehlt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The amount of items to buy is missing."</text>
   </message>
   <message name="error25" section="errors">
     <type>
@@ -6494,8 +5001,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Fluch verhindert das."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - A curse prevents this from happening."</text>
   </message>
   <message name="error24" section="errors">
     <type>
@@ -6503,8 +5008,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Belagerungszustand macht Spionage unmöglich."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Espionage was not possible due to siege."</text>
   </message>
   <message name="error23" section="errors">
     <type>
@@ -6512,8 +5015,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Belagerungszustand macht die Kontaktaufnahme unmöglich."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Contact was not possible due to siege."</text>
   </message>
   <message name="error22" section="errors">
     <type>
@@ -6521,8 +5022,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Befehl wurde nicht erkannt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Unknown command."</text>
   </message>
   <message name="error21" section="errors">
     <type>
@@ -6530,8 +5029,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dazu gibt es keine Informationen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There is no information available for the request."</text>
   </message>
   <message name="error20" section="errors">
     <type>
@@ -6539,8 +5036,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Schiff wurde nicht gefunden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The ship could not be found."</text>
   </message>
   <message name="error19" section="errors">
     <type>
@@ -6548,8 +5043,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Schiff muß erst verlassen werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - First you have to leave the ship."</text>
   </message>
   <message name="error18" section="errors">
     <type>
@@ -6557,8 +5050,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Schiff ist zu schwer beladen, um in See zu stechen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The ship is too heavily loaded to sail."</text>
   </message>
   <message name="error_flying_ship_too_big" section="errors">
     <type>
@@ -6567,8 +5058,6 @@
       <arg name="ship" type="ship"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $ship($ship) ist zu groß, um fliegen zu können."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $ship($ship) is too bulky to fly."</text>
   </message>
   <message name="error16" section="errors">
     <type>
@@ -6576,8 +5065,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Schiff ist schon fertig."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The ship is already completed."</text>
   </message>
   <message name="error15" section="errors">
     <type>
@@ -6585,8 +5072,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Schiff ist noch nicht fertig gebaut."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The ship has not yet been completed."</text>
   </message>
   <message name="error14" section="errors">
     <type>
@@ -6594,8 +5079,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Schiff ist auf hoher See."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The ship is off shore."</text>
   </message>
   <message name="error13" section="errors">
     <type>
@@ -6603,8 +5086,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Schiff hat sich bereits bewegt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The ship has moved already."</text>
   </message>
   <message name="error150" section="errors">
     <type>
@@ -6612,8 +5093,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Besitzer muss das Gebäude zuerst verlassen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The owner must first LEAVE the building."</text>
   </message>
   <message name="error12" section="errors">
     <type>
@@ -6621,8 +5100,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Schiff gehört uns nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The ship is not ours."</text>
   </message>
   <message name="error1222" section="errors">
     <type>
@@ -6630,8 +5107,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Gebäude gehört uns nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The building is not ours."</text>
   </message>
   <message name="error11" section="errors">
     <type>
@@ -6639,8 +5114,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Schiff befindet sich auf hoher See."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The ship is still off shore."</text>
   </message>
   <message name="error10" section="errors">
     <type>
@@ -6648,8 +5121,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das macht wenig Sinn."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - That does not make much sense."</text>
   </message>
   <message name="error9" section="errors">
     <type>
@@ -6657,8 +5128,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das kann man nicht sabotieren."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - That cannot be sabotaged."</text>
   </message>
   <message name="error8" section="errors">
     <type>
@@ -6666,8 +5135,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das ist sinnlos."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - That is useless."</text>
   </message>
   <message name="error7" section="errors">
     <type>
@@ -6675,8 +5142,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das geht nicht mehr."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This is no longer possible."</text>
   </message>
   <message name="error6" section="errors">
     <type>
@@ -6684,8 +5149,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Gebäude wurde nicht gefunden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Building could not be found."</text>
   </message>
   <message name="error5" section="errors">
     <type>
@@ -6693,8 +5156,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Gebäude gehört uns nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The building is not ours."</text>
   </message>
   <message name="error4" section="errors">
     <type>
@@ -6702,8 +5163,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Das Gebäude ist bereits fertig."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The building is already completed."</text>
   </message>
   <message name="error292" section="errors">
     <type>
@@ -6711,8 +5170,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit kann nicht unterrichtet werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit cannot be taught."</text>
   </message>
   <message name="error3" section="errors">
     <type>
@@ -6720,8 +5177,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Beschreibung zu lang - gekürzt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Description has been cut (too long)."</text>
   </message>
   <message name="error2" section="errors">
     <type>
@@ -6729,8 +5184,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Auf hoher See kann man nicht bewachen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You cannot guard off shore."</text>
   </message>
   <message name="error1" section="errors">
     <type>
@@ -6738,8 +5191,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Auf dem Schiff befinden sich zuwenig erfahrene Seeleute."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There are not enough experienced sailors on board the ship."</text>
   </message>
   <message name="mistake" section="errors">
     <type>
@@ -6748,16 +5199,12 @@
       <arg name="command" type="order"/>
       <arg name="error" type="string"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - ${error}."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - ${error}."</text>
   </message>
   <message name="usepotion" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="potion" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) benutzt $resource($potion,1)."</text>
-    <text locale="en">"$unit($unit) uses $resource($potion,1)."</text>
   </message>
   <message name="use_item" section="events">
     <type>
@@ -6765,8 +5212,6 @@
       <arg name="item" type="resource"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) benutzt $int($amount) $resource($item,$amount)."</text>
-    <text locale="en">"$unit($unit) uses $int($amount) $resource($item,$amount)."</text>
   </message>
   <message name="no_attack_after_advance" section="errors">
     <type>
@@ -6774,8 +5219,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit ist noch zu erschöpft vom Einmarsch um zu attackieren."</text>
-    <text locale="en">"'$order($command)' - $unit($unit) marched into $region($region) during the last turn and is too exhausted to attack."</text>
   </message>
   <message name="race_no_attack" section="errors">
     <type>
@@ -6784,8 +5227,6 @@
       <arg name="command" type="order"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) sind friedliebend und attackieren niemand."</text>
-    <text locale="en">"'$order($command)' - $race($race,0) are peace-loving and will not attack anyone."</text>
   </message>
   <message name="building_needed" section="production">
     <type>
@@ -6794,8 +5235,6 @@
       <arg name="command" type="order"/>
       <arg name="building" type="string"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit steht nicht im benötigten Gebäude, $localize($building)."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit must be in a $localize($building) to produce this."</text>
   </message>
   <message name="skill_needed" section="errors">
     <type>
@@ -6804,8 +5243,6 @@
       <arg name="command" type="order"/>
       <arg name="skill" type="skill"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dazu braucht man das Talent $skill($skill)."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This requires the skill $skill($skill)."</text>
   </message>
   <message name="plant_skills" section="errors">
     <type>
@@ -6816,8 +5253,6 @@
       <arg name="minskill" type="int"/>
       <arg name="product" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Man benötigt mindestens $int($minskill) $skill($skill), um $resource($product,0) zu pflanzen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - At least $skill($skill) $int($minskill) is needed for planting $resource($product,0)."</text>
   </message>
   <message name="manufacture_skills" section="errors">
     <type>
@@ -6828,15 +5263,11 @@
       <arg name="minskill" type="int"/>
       <arg name="product" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Man benötigt mindestens $int($minskill) $skill($skill), um $resource($product,0) zu produzieren."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You need at least $int($minskill) $skill($skill), to produce $resource($product,0)."</text>
   </message>
   <message name="msg_event" section="events">
     <type>
       <arg name="string" type="string"/>
     </type>
-    <text locale="de">"$string"</text>
-    <text locale="en">"$string"</text>
   </message>
 
   <message name="give_person" section="economy">
@@ -6845,8 +5276,6 @@
       <arg name="amount" type="int"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) übergibt $int($amount) Person$if($eq($amount,1),"","en") an $unit($target)."</text>
-    <text locale="en">"$unit($unit) transfers $int($amount) person$if($eq($amount,1),"","s") to $unit($target)."</text>
   </message>
 
   <message name="receive_person" section="economy">
@@ -6855,8 +5284,6 @@
       <arg name="amount" type="int"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($target) erhält $int($amount) Person$if($eq($amount,1),"","en") von $unit($unit)."</text>
-    <text locale="en">"$unit($target) receives $int($amount) person$if($eq($amount,1),"","s") from $unit($unit)."</text>
   </message>
 
   <message name="give" section="economy">
@@ -6866,8 +5293,6 @@
       <arg name="resource" type="resource"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) übergibt $int($amount) $resource($resource,$amount) an $unit($target)."</text>
-    <text locale="en">"$unit($unit) gives $int($amount) $resource($resource,$amount) to $unit($target)."</text>
   </message>
 
   <message name="receive" section="economy">
@@ -6877,8 +5302,6 @@
       <arg name="resource" type="resource"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($target) erhält $int($amount) $resource($resource,$amount) von $unit($unit)."</text>
-    <text locale="en">"$unit($target) receives $int($amount) $resource($resource,$amount) from $unit($unit)."</text>
   </message>
 
   <message name="give_person_ocean" section="economy">
@@ -6886,8 +5309,6 @@
       <arg name="unit" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) ertränkt $int($amount) Person$if($eq($amount,1),"","en")."</text>
-    <text locale="en">"$unit($unit) drowns $int($amount)."</text>
   </message>
 
   <message name="give_person_peasants" section="economy">
@@ -6895,8 +5316,6 @@
       <arg name="unit" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) übergibt $int($amount) Person$if($eq($amount,1),"","en") an die Bauern."</text>
-    <text locale="en">"$unit($unit) transfers $int($amount) person$if($eq($amount,1),"","s") to the local peasants."</text>
   </message>
 
   <message name="give_peasants" section="economy">
@@ -6905,8 +5324,6 @@
       <arg name="amount" type="int"/>
       <arg name="resource" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) übergibt $int($amount) $resource($resource,$amount) an die Bauern."</text>
-    <text locale="en">"$unit($unit) gives $int($amount) $resource($resource,$amount) to the local peasants."</text>
   </message>
 
   <message name="maintenance" section="economy">
@@ -6914,8 +5331,6 @@
       <arg name="unit" type="unit"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($unit) bezahlt den Unterhalt von $building($building)."</text>
-    <text locale="en">"$unit($unit) pays the maintenance for $building($building)."</text>
   </message>
   <message name="maintenancespecialfail" section="errors">
     <type>
@@ -6923,23 +5338,17 @@
       <arg name="item" type="resource"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($unit) fehlen $resource($item,0) für den Betrieb von $building($building)."</text>
-    <text locale="en">"$unit($unit) lacks $resource($item,0) to operate $building($building)."</text>
   </message>
   <message name="maintenancefail" section="errors">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($unit) kann den Unterhalt von $building($building) nicht bezahlen."</text>
-    <text locale="en">"$unit($unit) cannot pay the maintenance for $building($building)."</text>
   </message>
   <message name="maintenance_noowner" section="errors">
     <type>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"Der Unterhalt von $building($building) konnte nicht gezahlt werden, das Gebäude war diese Woche nicht funktionstüchtig."</text>
-    <text locale="en">"The upkeep for $building($building) was not paid, the building was not operational this week."</text>
   </message>
   <message name="income_tradetax" section="economy">
     <type>
@@ -6947,15 +5356,11 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) verdient am Handel in $region($region) Steuern in Höhe von $int($amount) Silber."</text>
-    <text locale="en">"$unit($unit) collected $int($amount) silver trade tax in $region($region)."</text>
   </message>
   <message name="pest" section="events">
     <type>
       <arg name="dead" type="int"/>
     </type>
-    <text locale="de">"Hier wütete die Pest, und $int($dead) Bauern starben."</text>
-    <text locale="en">"The region is visited by the plague and $int($dead) peasants died."</text>
   </message>
   <message name="error131" section="errors">
     <type>
@@ -6963,8 +5368,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Um in Gletschern Straßen bauen zu können, muß zuerst ein Tunnel errichtet werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You must build a tunnel before building roads through glaciers."</text>
   </message>
   <message name="error130" section="errors">
     <type>
@@ -6972,8 +5375,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Syntax: MAGIEGEBIET [1-5]."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Syntax: MAGIC SPHERE [1-5]."</text>
   </message>
   <message name="giverestriction" section="errors">
     <type>
@@ -6982,30 +5383,18 @@
       <arg name="command" type="order"/>
       <arg name="turns" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Deine Partei muss mindestens $int($turns) alt sein, um etwas an andere Parteien übergeben zu können."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Your faction must be at least $int($turns) weeks old to give something to another faction."</text>
   </message>
 
   <message name="nmr_warning" section="errors">
-  <type/>
-    <text locale="de">Deine Partei hat letzte Runde keinen Zug
-    abgegeben!</text>
-    <text locale="en">No orders were received for your faction!</text>
-    <text locale="fr">Aucun ordre reçu pour votre faction !</text>
   </message>
 
   <message name="nmr_warning_final" section="errors">
-  <type/>
-    <text locale="de">"Bitte sende die Befehle nächste Runde ein, wenn du weiterspielen möchtest."</text>
-    <text locale="en">"Please send in orders for the next turn if you want to continue playing."</text>
   </message>
 
   <message name="newbieimmunity" section="nr">
     <type>
       <arg name="turns" type="int"/>
     </type>
-    <text locale="de">"Deine Partei ist noch $int($turns) Wochen immun gegen Angriffe."</text>
-    <text locale="en">"Your faction is immune against assaults for $int($turns) more weeks."</text>
   </message>
   <message name="alliance::kickedout" section="events">
     <type>
@@ -7013,23 +5402,17 @@
       <arg name="member" type="faction"/>
       <arg name="alliance" type="alliance"/>
     </type>
-    <text locale="de">"$faction($member) ist mit $int($votes) Stimmen aus $alliance($alliance) ausgeschlossen worden."</text>
-    <text locale="en">"$faction($member) was kicked from $alliance($alliance) by $int($votes) of the alliance's members."</text>
   </message>
   <message name="alliance::lost" section="events">
     <type>
       <arg name="alliance" type="alliance"/>
     </type>
-    <text locale="de">"$alliance($alliance) scheidet aus dem Spiel aus, nachdem alle Tempel verloren gingen."</text>
-    <text locale="en">"$alliance($alliance) has to leave the game after all their temples were lost."</text>
   </message>
   <message name="alliance::kickattempt" section="events">
     <type>
       <arg name="votes" type="int"/>
       <arg name="alliance" type="alliance"/>
     </type>
-    <text locale="de">"$int($votes) Mitglieder von $alliance($alliance) haben versucht, Deine Partei aus der Allianz auszuschliessen."</text>
-    <text locale="en">"$int($votes) members of $alliance($alliance) tried to kick you out of the alliance."</text>
   </message>
   <message name="wdw_pyramidspell_found" section="events">
     <type>
@@ -7037,8 +5420,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - In dieser Regione können Pyramiden gebaut werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Pyramids may be build in this region."</text>
   </message>
   
   <message name="error_spell_on_ship_already" section="errors">
@@ -7048,8 +5429,6 @@
       <arg name="command" type="order"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Auf $ship($ship) liegt beeits ein Zauber."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There is already a spell on $ship($ship)."</text>
   </message>
   
   <message name="error_spell_on_flying_ship" section="errors">
@@ -7059,8 +5438,6 @@
       <arg name="command" type="order"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es ist zu gefährlich, diesen Zauber auf das fliegende Schiff $ship($ship) zu legen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - It is far too dangerous to put this spell on the flying ship $ship($ship)."</text>
   </message>
   
   <message name="wdw_pyramidspell_notfound" section="events">
@@ -7071,8 +5448,6 @@
       <arg name="mindist" type="int"/>
       <arg name="maxdist" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - In dieser Region können keine Pyramiden gebaut werden. Die nächste Pyramidenregion ist zwischen $int($mindist) und $int($maxdist) Regionen entfernt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No pyramids may be build in this region. The closest region to build a pyramid in is between $int($mindist) and $int($maxdist) regions away."</text>
   </message>
 
   <message name="wormhole_requirements" section="errors">
@@ -7080,110 +5455,80 @@
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) kann in $region($region) nicht durch das Wurmloch reisen, da die Einheit entweder zu gross ist oder teure Talente besitzt."</text>
-    <text locale="en">"$unit($unit) cannot travel through the wormhole in $region($region) because the unit is either too big or has restricted skills."</text>
   </message>
   <message name="wormhole_exit" section="events">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) reist durch ein Wurmloch nach $region($region)."</text>
-    <text locale="en">"$unit($unit) travels through a wormhole to $region($region)."</text>
   </message>
   <message name="wormhole_appear" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"In $region($region) erscheint ein Wurmloch."</text>
-    <text locale="en">"A wormhole appears in $region($region)."</text>
   </message>
   <message name="wormhole_dissolve" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Das Wurmloch in $region($region) schließt sich."</text>
-    <text locale="en">"The wormhole in $region($region) disappears."</text>
   </message>
   <message name="useflamingsword" section="battle">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$int($amount) Krieger von $unit($unit) benutzen ihre Flammenschwerter."</text>
-    <text locale="en">"$int($amount) fighters of $unit($unit) are using their flaming sword."</text>
   </message>
   <message name="usecatapult" section="battle">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$int($amount) Krieger von $unit($unit) feuern ihre Katapulte ab."</text>
-    <text locale="en">"$int($amount) fighters of $unit($unit) launch their catapults."</text>
   </message>
   <message name="start_battle" section="battle">
     <type>
       <arg name="factions" type="string"/>
     </type>
-    <text locale="de">"Der Kampf wurde ausgelöst von ${factions}."</text>
-    <text locale="en">"The battle was initiated by ${factions}."</text>
   </message>
   <message name="potionsave" section="battle">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"Eine Person von $unit($unit) konnte durch einen Heiltrank überleben."</text>
-    <text locale="en">"A fighter of $unit($unit) was saved by a healing potion."</text>
   </message>
   <message name="tactics_lost" section="battle">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) konnte dem Gegner eine Falle stellen."</text>
-    <text locale="en">"$unit($unit) lured the enemy into an ambush."</text>
   </message>
   <message name="tactics_won" section="battle">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) überrascht den Gegner."</text>
-    <text locale="en">"$unit($unit) surprises the enemies."</text>
   </message>
   <message name="spell_failed" section="battle">
     <type>
       <arg name="unit" type="unit"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"$unit($unit) versucht $spell($spell) zu zaubern, doch der Zauber schlägt fehl!"</text>
-    <text locale="en">"$unit($unit) tries to cast $spell($spell), but the spell fails!"</text>
   </message>
   <message name="aborted_battle" section="battle">
     <type>
     </type>
-    <text locale="de">"Der Kampf wurde abgebrochen, da alle Verteidiger flohen."</text>
-    <text locale="en">"The battle was aborted because all enemies escaped."</text>
   </message>
   <message name="battle_row" section="battle">
     <type>
       <arg name="row" type="int"/>
     </type>
-    <text locale="de">"... in der $int($row). Kampflinie:"</text>
-    <text locale="en">"... in combat rank $int($row):"</text>
   </message>
   <message name="spell_out_of_range" section="battle">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell), aber niemand war in Reichweite."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell), but nobody was in range."</text>
   </message>
 
   <message name="para_after_battle" section="battle">
     <type>
     </type>
-    <text locale="de">"Einheiten nach dem Kampf:"</text>
-    <text locale="en">"Units after the battle:"</text>
   </message>
   
   <message name="sp_wolfhowl_effect" section="battle">
@@ -7192,48 +5537,36 @@
       <arg name="amount" type="int"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($mage) ruft $int($amount) $race($race, $amount) zu Hilfe."</text>
-    <text locale="en">"$unit($mage) calls for the help of $int($amount) $race($race, $amount)."</text>
   </message>
   
   <message name="sp_shadowknights_effect" section="battle">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) beschwört Trugbilder herauf."</text>
-    <text locale="en">"$unit($mage) summons a mirage."</text>
   </message>
   
   <message name="sp_chaosrow_effect_0" section="battle">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) murmelt eine düster klingende Formel. Ein plötzlicher Tumult entsteht, der sich jedoch schnell wieder legt."</text>
-    <text locale="en">"$unit($mage) mumbles arcane words. There is a sudden hubbub, but order is restored quickly."</text>
   </message>
   
   <message name="sp_chaosrow_effect_1" section="battle">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) murmelt eine düster klingende Formel. Ein plötzlicher Tumult entsteht und bringt die Kampfaufstellung durcheinander."</text>
-    <text locale="en">"$unit($mage) mumbles arcane words. There is a sudden hubbub and the battle order is disturbed."</text>
   </message>
   
   <message name="sp_confusion_effect_0" section="battle">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) stimmt einen seltsamen Gesang an. Ein plötzlicher Tumult entsteht, der sich jedoch schnell wieder legt."</text>
-    <text locale="en">"$unit($mage) intones a mysterious chant. There is a sudden hubbub, but order is restored quickly."</text>
   </message>
   
   <message name="sp_confusion_effect_1" section="battle">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) stimmt einen seltsamen Gesang an. Ein plötzlicher Tumult entsteht und bringt die Kampfaufstellung durcheinander."</text>
-    <text locale="en">"$unit($mage) begins a mysterious chant. Great confusion sweeps through the ranks of the enemy."</text>
   </message>
   
   <message name="sp_strongwalls_effect" section="battle">
@@ -7241,23 +5574,17 @@
       <arg name="mage" type="unit"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($mage) läßt die Mauern von $building($building) in einem unheimlichen magischen Licht erglühen."</text>
-    <text locale="en">"$unit($mage) causes the walls of $building($building) to glow in an eerie magic light."</text>
   </message>
   
   <message name="para_lineup_battle" section="battle">
     <type>
       <arg name="turn" type="int"/>
     </type>
-    <text locale="de">"Einheiten vor der $int($turn). Runde:"</text>
-    <text locale="en">"Units before turn $int($turn):"</text>
   </message>
   <message name="header_battle" section="battle">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"In $region($region) findet ein Kampf statt."</text>
-    <text locale="en">"There is a battle in $region($region)."</text>
   </message>
   <message name="cast_combatspell" section="battle">
     <type>
@@ -7265,8 +5592,6 @@
       <arg name="spell" type="spell"/>
       <arg name="dead" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell): $int($dead) $if($eq($dead,1),"Krieger wurde", "Krieger wurden") getötet."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell): $int($dead) $if($eq($dead,1),"enemy was", "enemies were") killed."</text>
   </message>
 
   <message name="earthquake_effect" section="magic">
@@ -7274,8 +5599,6 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) läßt die Erde in $region($region) erzittern."</text>
-    <text locale="en">"$unit($mage) makes the earth shake in $region($region)."</text>
   </message>
   
   <message name="sp_drought_effect" section="magic">
@@ -7283,16 +5606,12 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) verflucht das Land in $region($region), und eine Dürreperiode beginnt."</text>
-    <text locale="en">"$unit($mage) puts a curse on the lands of $region($region) and a drought sets in."</text>
   </message>
   
   <message name="sp_clone_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) erschafft einen Klon."</text>
-    <text locale="en">"$unit($mage) creates a clone."</text>
   </message>
   
   <message name="sp_dreamreading_effect" section="magic">
@@ -7301,8 +5620,6 @@
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) verliert sich in die Träume von $unit($unit) und erhält einen Eindruck von $region($region)."</text>
-    <text locale="en">"$unit($mage) is lost in the dreams of $unit($unit) and gets a glimps into $region($region)."</text>
   </message>
   
   <message name="sp_sweetdreams_effect" section="magic">
@@ -7311,8 +5628,6 @@
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) verschafft $unit($unit) ein schönes Nachtleben in $region($region)."</text>
-    <text locale="en">"$unit($mage) causes $unit($unit) to have a wonderful night in $region($region)."</text>
   </message>
   
   <message name="sp_disturbingdreams_effect" section="magic">
@@ -7320,8 +5635,6 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) sorgt für schlechten Schlaf in $region($region)."</text>
-    <text locale="en">"$unit($mage) disturbs everyone's dreams in $region($region)."</text>
   </message>
   
   <message name="summon_effect" section="magic">
@@ -7330,8 +5643,6 @@
       <arg name="amount" type="int"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($mage) beschwört $int($amount) $race($race,$amount)."</text>
-    <text locale="en">"$unit($mage) summons  $int($amount) $race($race,$amount)."</text>
   </message>
   
   <message name="forestfire_effect" section="magic">
@@ -7340,8 +5651,6 @@
       <arg name="region" type="region"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) erschafft in $region($region) eine verheerende Feuersbrunst. $int($amount) Bäume fallen den Flammen zum Opfer."</text>
-    <text locale="en">"$unit($mage) creates a flaming inferno in $region($region). $int($amount) trees fall victim to the flames."</text>
   </message>
   
   <message name="homestone_effect" section="magic">
@@ -7349,8 +5658,6 @@
       <arg name="mage" type="unit"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"Mit einem Ritual bindet $unit($mage) die magischen Kräfte der Erde in die Mauern von $building($building)."</text>
-    <text locale="en">"A magic ritual by $unit($mage) binds magic energies to the walls of $building($building)."</text>
   </message>
 
   <message name="blessedstonecircle_effect" section="magic">
@@ -7358,8 +5665,6 @@
       <arg name="mage" type="unit"/>
       <arg name="building" type="building"/>
     </type>
-    <text locale="de">"$unit($mage) weiht $building($building)."</text>
-    <text locale="en">"$unit($mage) blesses $building($building)."</text>
   </message>
 
   <message name="drought_effect_1" section="magic">
@@ -7367,8 +5672,6 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) ruft das Feuer der Sonne auf $region($region) hinab. Eis schmilzt und verwandelt sich in Morast. Reißende Ströme spülen die mageren Felder weg und ersäufen Mensch und Tier. Was an Bauten nicht den Fluten zum Opfer fiel, verschlingt der Morast. Die sengende Hitze verändert die Region für immer."</text>
-    <text locale="en">"$unit($mage) calls the torching power of the sun upon $region($region). Ice melts and turns the lands into swamps. Powerful rivers wash away the fertile soil and drown people and animals alike. What buildings have not succumbed to the floods sink into the mire. The torrid sun changes the region forever."</text>
   </message>
 
   <message name="drought_effect_2" section="magic">
@@ -7376,8 +5679,6 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) ruft das Feuer der Sonne auf $region($region) hinab. Die Felder verdorren und Pferde verdursten. Die Hungersnot kostet vielen Bauern das Leben. Vertrocknete Bäume recken ihre kahlen Zweige in den blauen Himmel, von dem erbarmungslos die sengende Sonne brennt."</text>
-    <text locale="en">"$unit($mage) calls the torching power of the sun upon $region($region). The crops wither, horses die of thirst. A famine claims the lives of many peasants. The trees die and their bald branches cannot protect from the torrid sun that mercilessly burns the grounds."</text>
   </message>
 
   <message name="drought_effect_3" section="magic">
@@ -7385,8 +5686,6 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) ruft das Feuer der Sonne auf $region($region) hinab. Die Felder verdorren und Pferde verdursten. Die Hungersnot kostet vielen Bauern das Leben. Vertrocknete Bäume recken ihre kahlen Zweige in den blauen Himmel, von dem erbarmungslos die sengende Sonne brennt. Die Dürre verändert die Region für immer."</text>
-    <text locale="en">"$unit($mage) calls the torching power of the sun upon $region($region). The crops wither, horses die of thirst. A famine claims the lives of many peasants. The trees die and their bald branches cannot protect from the torrid sun that mercilessly burns the grounds. The drought permanently alters the region."</text>
   </message>
 
   <message name="drought_effect_4" section="magic">
@@ -7394,40 +5693,28 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($mage) ruft das Feuer der Sonne auf $region($region) hinab. Das Eis zerbricht und eine gewaltige Flutwelle verschlingt die Region."</text>
-    <text locale="en">"$unit($mage) calls the torching power of the sun upon $region($region). The ice melts and and the region is consumed by a tidal wave."</text>
   </message>
 
   <message name="generous_effect_1" section="magic">
-    <text locale="de">"Die Darbietungen eines fahrenden Gauklers begeistern die Leute. Die fröhliche und ausgelassene Stimmung seiner Lieder überträgt sich auf alle Zuhörer."</text>
-    <text locale="en">"A touring minstrel entertains the locals. The joyous and generous disposition of his songs prove infectious."</text>
   </message>
 
   <message name="generous_effect_0" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"Die Darbietungen von $unit($mage) begeistern die Leute. Die fröhliche und ausgelassene Stimmung seiner Lieder überträgt sich auf alle Zuhörer."</text>
-    <text locale="en">"$unit($mage) entertains the locals. The joyous and generous disposition of his songs prove infectious."</text>
   </message>
   <message name="song_of_peace_effect_1" section="magic">
-    <text locale="de">"In der Luft liegt ein wunderschönes Lied, dessen friedfertiger Stimmung sich niemand entziehen kann. Einige Leute werfen sogar ihre Waffen weg."</text>
-    <text locale="en">"A wondrous song fills the air and enchants the public. The song's peaceful melody makes several listeners drop their weapons."</text>
   </message>
   <message name="song_of_peace_effect_0" section="magic">
     <type>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"Die Gesangskunst von $unit($mage) begeistert die Leute. Die friedfertige Stimmung des Lieds überträgt sich auf alle Zuhörer. Einige werfen ihre Waffen weg."</text>
-    <text locale="en">"The marvelous singing of $unit($mage) enchants the public. The song's peaceful melody makes several listeners drop their weapons."</text>
   </message>
   <message name="summonshadow_effect" section="magic">
     <type>
       <arg name="mage" type="unit"/>
       <arg name="number" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) beschwört $int($number) Dämonen aus dem Reich der Schatten."</text>
-    <text locale="en">"$unit($mage) summons $int($number) demons from the realm of shadows."</text>
   </message>
 
   <message name="cast_spell_effect" section="magic">
@@ -7435,8 +5722,6 @@
       <arg name="mage" type="unit"/>
       <arg name="spell" type="spell"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell)."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell)."</text>
   </message>
 
   <message name="sp_mindblast_effect" section="magic">
@@ -7446,8 +5731,6 @@
       <arg name="amount" type="int"/>
       <arg name="dead" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell). $int($amount) Krieger verloren Erinnerungen, $int($dead) wurden getötet."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell). $int($amount) warriors lose their memories, $int($dead) were killed."</text>
   </message>
 
   <message name="sp_mindblast_temp_effect" section="magic">
@@ -7456,8 +5739,6 @@
       <arg name="spell" type="spell"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) zaubert $spell($spell). $int($amount) Krieger verloren kurzzeitig ihr Gedächtnis."</text>
-    <text locale="en">"$unit($mage) casts $spell($spell). $int($amount) fighters are temporarily losing some of their memories."</text>
   </message>
 
   <message name="killed_battle" section="battle">
@@ -7465,8 +5746,6 @@
       <arg name="unit" type="unit"/>
       <arg name="dead" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) tötete $int($dead) Krieger."</text>
-    <text locale="en">"$unit($unit) killed $int($dead) opponents."</text>
   </message>
   <message name="army_report" section="battle">
     <type>
@@ -7476,8 +5755,6 @@
       <arg name="fled" type="int"/>
       <arg name="survived" type="int"/>
     </type>
-    <text locale="de">"Heer $int($index)($abbrev): $int($dead) Tote, $int($fled) Geflohene, $int($survived) Überlebende."</text>
-    <text locale="en">"Army $int($index)($abbrev): $int($dead) dead, $int($fled) fled, $int($survived) survivors."</text>
   </message>
   <message name="spellfail::nolevel" section="errors">
     <type>
@@ -7485,8 +5762,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($mage) in $region($region): '$order($command)' - Dieser Zauber kann nicht mit Stufenangabe gezaubert werden."</text>
-    <text locale="en">"$unit($mage) in $region($region): '$order($command)' - This spell cannot be cast with variable level."</text>
   </message>
   <message name="spellfail::noway" section="magic">
     <type>
@@ -7494,8 +5769,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dorthin führt kein Weg."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There is no route leading there."</text>
   </message>
   <message name="spellfail::nocontact" section="magic">
     <type>
@@ -7504,8 +5777,6 @@
       <arg name="command" type="order"/>
       <arg name="target" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Zu $region($target) kann kein Kontakt hergestellt werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $region($target) could not be contacted."</text>
   </message>
   <message name="spellfail::contact" section="magic">
     <type>
@@ -7514,8 +5785,6 @@
       <arg name="command" type="order"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit $unit($target) hat keinen Kontakt mit uns aufgenommen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit $unit($target) did not contact us."</text>
   </message>
 
   <message name="block_spell" section="magic">
@@ -7524,8 +5793,6 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Antimagie von $unit.dative($self) blockiert in $region($region) einen Zauber von $unit.dative($mage)."</text>
-    <text locale="en">"In $region($region), anti-magic from $unit($self) blocks the spell of $unit($mage)."</text>
   </message>
 
   <message name="reduce_spell" section="magic">
@@ -7534,8 +5801,6 @@
       <arg name="mage" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($self) schwächt in $region($region) einen Zauber von $unit.dative($mage) durch Antimagie ab."</text>
-    <text locale="en">"In $region($region), anti-magic from $unit($self) reduces the effect of $unit($mage)'s spell."</text>
   </message>
 
   <message name="hornofpeace_u_success" section="magic">
@@ -7545,8 +5810,6 @@
       <arg name="command" type="order"/>
       <arg name="pacified" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $int($pacified) Regionen wurden befriedet."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $int($pacified) regions have been pacified."</text>
   </message>
 
   <message name="hornofpeace_u_nosuccess" section="magic">
@@ -7556,8 +5819,6 @@
       <arg name="command" type="order"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Keine Region konnte befriedet werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - No region could be pacified."</text>
   </message>
 
   <message name="hornofpeace_r_success" section="magic">
@@ -7565,8 +5826,6 @@
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) bläst das Horn des Tanzes. In der ganzen Region breitet sich eine friedliche Feststimmmung aus."</text>
-    <text locale="en">"$unit($unit) in $region($region) blows the Horn of Dancing. Peaceful harmony spreads over the region."</text>
   </message>
 
   <message name="hornofpeace_r_nosuccess" section="magic">
@@ -7574,8 +5833,6 @@
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region) bläst das Horn des Tanzes, doch niemand hier lässt sich von Stimmung anstecken."</text>
-    <text locale="en">"$unit($unit) in $region($region) blows the Horn of Dancing, but nobody here gets into the mood."</text>
   </message>
 
   <message name="trappedairelemental_success" section="magic">
@@ -7585,8 +5842,6 @@
       <arg name="command" type="order"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die $ship($ship) wird jetzt schneller ihr Ziel erreichen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The $ship($ship) will now be faster."</text>
   </message>
 
   <message name="aurapotion50_effect" section="magic">
@@ -7595,8 +5850,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Magier fühlt sich durch den Trank magische gestärkt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The mage is magically invigorated."</text>
   </message>
 
   <message name="bagpipeoffear_faction" section="magic">
@@ -7606,8 +5859,6 @@
       <arg name="command" type="order"/>
       <arg name="money" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Ausser sich vor Furcht geben die Bauern dem Barden $int($money) Silber."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Stricken with fear the peasants give the bard $int($money) silver."</text>
   </message>
 
   <message name="bagpipeoffear_region" section="magic">
@@ -7615,8 +5866,6 @@
       <arg name="unit" type="unit"/>
       <arg name="money" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) spielt einen Dudelsack. Ausser sich vor Furcht geben die Bauern $int($money) Silber."</text>
-    <text locale="en">"$unit($unit) plays the bagpipe. Stricken with fear the peasants give $int($money) silver."</text>
   </message>
 
   <message name="spellfail_distance" section="errors">
@@ -7626,8 +5875,6 @@
       <arg name="unit" type="unit"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Region ist zu weit entfernt."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - That region is too far away."</text>
   </message>
 
   <message name="spellfail_block" section="errors">
@@ -7636,24 +5883,18 @@
       <arg name="region" type="region"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Wege aus dieser Region sind blockiert."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The connections from to this regions are blocked."</text>
   </message>
 
   <message name="astral_appear" section="events">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) erscheint plötzlich."</text>
-    <text locale="en">"$unit($unit) appears."</text>
   </message>
 
   <message name="astral_disappear" section="events">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) wird durchscheinend und verschwindet."</text>
-    <text locale="en">"$unit($unit) disappears."</text>
   </message>
 
   <message name="fail_tooheavy" section="errors">
@@ -7663,8 +5904,6 @@
       <arg name="unit" type="unit"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($target) ist zu schwer."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($target) is too heavy."</text>
   </message>
 
   <message name="heroes_maxed" section="errors">
@@ -7675,8 +5914,6 @@
       <arg name="max" type="int"/>
       <arg name="count" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Partei hat bereits $int($count) von $int($max) Helden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The faction already has $int($count) of $int($max) heroes."</text>
   </message>
 
   <message name="heroes_race" section="errors">
@@ -7686,8 +5923,6 @@
       <arg name="unit" type="unit"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) können keine Helden erwählen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) cannot be heroes."</text>
   </message>
 
   <message name="hero_promotion" section="events">
@@ -7695,8 +5930,6 @@
       <arg name="unit" type="unit"/>
       <arg name="cost" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) wird mit $int($cost) Silber zum Helden ernannt."</text>
-    <text locale="en">"$unit($unit) uses $int($cost) silber for a promotion."</text>
   </message>
 
   <message name="heroes_cost" section="errors">
@@ -7707,16 +5940,12 @@
       <arg name="cost" type="int"/>
       <arg name="have" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Die Einheit hat nur $int($have) von $int($cost) benötigtem Silber."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The unit has $int($have) of $int($cost) silver required."</text>
   </message>
 
   <message name="tidalwave" section="events">
     <type>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"Eine gewaltige Flutwelle verschlingt $region($region) und alle Bewohner."</text>
-    <text locale="en">"A tidal wave wipes out $region($region) and all who lived there."</text>
   </message>
 
   <message name="tidalwave_kill" section="events">
@@ -7724,8 +5953,6 @@
       <arg name="region" type="region"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"Eine gewaltige Flutwelle verschlingt $unit($unit) in $region($region)."</text>
-    <text locale="en">"A tidal wave wipes out $region($region) and kills $unit($unit)."</text>
   </message>
 
   <message name="astralshield_activate" section="events">
@@ -7733,8 +5960,6 @@
       <arg name="region" type="region"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) reaktiviert den astralen Schutzschild in $region($region)."</text>
-    <text locale="en">"$unit($unit) reactivates the astral protection shield in $region($region)."</text>
   </message>
 
   <message name="dissolve_units_1" section="events">
@@ -7744,8 +5969,6 @@
       <arg name="number" type="int"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),"kehrte auf seine", "kehrten auf ihre") Felder zurück."</text>
-    <text locale="en">"$unit($unit) in $region($region): $int($number) $race($race,$number) returned to the fields."</text>
   </message>
 
   <message name="dissolve_units_2" section="events">
@@ -7755,8 +5978,6 @@
       <arg name="number" type="int"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),"wurde zum Baum", "wurden zu Bäumen")."</text>
-    <text locale="en">"$unit($unit) in $region($region): $int($number) $race($race,$number) turned into $if($eq($number,1),"a tree", "trees")."</text>
   </message>
 
   <message name="dissolve_units_3" section="events">
@@ -7766,8 +5987,6 @@
       <arg name="number" type="int"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),"verfaulte", "verfaulten")."</text>
-    <text locale="en">"$unit($unit) in $region($region): $int($number) $race($race,$number) whithered and died."</text>
   </message>
 
   <message name="dissolve_units_4" section="events">
@@ -7777,8 +5996,6 @@
       <arg name="number" type="int"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),"zerfiel", "zerfielen") zu Staub."</text>
-    <text locale="en">"$unit($unit) in $region($region): $int($number) $race($race,$number) turned to dust."</text>
   </message>
 
   <message name="dissolve_units_5" section="events">
@@ -7788,9 +6005,6 @@
       <arg name="number" type="int"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): $int($number) $race($race,$number) $if($eq($number,1),"verschwand", "verschwanden") über Nacht."</text>
-    <text locale="en">"$unit($unit) in $region($region): $int($number)
-    $race($race,$number) disappeared in the night."</text>
   </message>
 
   <message name="forestfire_spread" section="events">
@@ -7799,8 +6013,6 @@
       <arg name="next" type="region"/>
       <arg name="trees" type="int"/>
     </type>
-    <text locale="de">"Der Waldbrand in $region($region) griff auch auf $region($next) über, und $int($trees) verbrannten."</text>
-    <text locale="en">"The fire in $region($region) spread to $region($next) and $int($trees) were burned."</text>
   </message>
 
   <message name="plague_spell" section="events">
@@ -7808,8 +6020,6 @@
       <arg name="region" type="region"/>
       <arg name="mage" type="unit"/>
     </type>
-    <text locale="de">"$unit($mage) ruft in $region($region) eine Pest hervor."</text>
-    <text locale="en">"$unit($mage) sends the plague on $region($region)."</text>
   </message>
 
   <message name="too_many_units_in_faction" section="errors">
@@ -7819,8 +6029,6 @@
       <arg name="unit" type="unit"/>
       <arg name="allowed" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Eine Partei darf nicht aus mehr als $int($allowed) Einheiten bestehen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - A faction may not consist of more than $int($allowed) units."</text>
   </message>
 
   <message name="too_many_units_in_alliance" section="errors">
@@ -7830,8 +6038,6 @@
       <arg name="unit" type="unit"/>
       <arg name="allowed" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Eine Allianz darf aus nicht mehr als $int($allowed) Einheiten bestehen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - An alliance may not consist of more than $int($allowed) units."</text>
   </message>
 
   <message name="itemcrumble" section="events">
@@ -7841,8 +6047,6 @@
       <arg name="item" type="resource"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): $int($amount) $resource($item,$amount) zerfallen zu Staub."</text>
-    <text locale="en">"$unit($unit) in $region($region): $int($amount) $resource($item,$amount) turn to dust."</text>
   </message>
 
   <message name="curseinfo::shipnodrift_1" section="magic">
@@ -7851,24 +6055,18 @@
       <arg name="duration" type="int"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Die $ship($ship) ist mit gutem Wind gesegnet$if($lt($duration,3),", doch der Zauber beginnt sich bereits aufzulösen",""). ($int36($id))"</text>
-    <text locale="en">"The $ship($ship) is blessed with favourable winds$if($lt($duration,3),", but the spell is starting to wear thin",""). ($int36($id))"</text>
   </message>
 
   <message name="curseinfo::flyingship" section="magic">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Kräftige Stürme haben dieses Schiff in die Luft gehoben. ($int36($id))"</text>
-    <text locale="en">"Powerful storms have lifted this ship high into the air. ($int36($id))"</text>
   </message>
 
   <message name="curseinfo::astralblock" section="magic">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Mächtige Magie verhindert den Kontakt zur Realität. ($int36($id))"</text>
-    <text locale="en">"Powerful magic disrupts our contact with reality. ($int36($id))"</text>
   </message>
 
   <message name="curseinfo::shipnodrift_0" section="magic">
@@ -7876,8 +6074,6 @@
       <arg name="ship" type="ship"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Ein silberner Schimmer umgibt die $ship($ship). ($int36($id))"</text>
-    <text locale="en">"A silvery shimmer surrounds the $ship($ship). ($int36($id))"</text>
   </message>
 
   <message name="curseinfo::magicrunes_building" section="magic">
@@ -7885,8 +6081,6 @@
       <arg name="building" type="building"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Auf den Mauern von $building($building) erkennt man seltsame Runen. ($int36($id))"</text>
-    <text locale="en">"The walls of $building($building) are inscribed with strange runes. ($int36($id))"</text>
   </message>
 
   <message name="item_create_spell" section="magic">
@@ -7895,8 +6089,6 @@
       <arg name="item" type="resource"/>
       <arg name="number" type="int"/>
     </type>
-    <text locale="de">"$unit($mage) erschafft $int($number) $resource($item,$number)."</text>
-    <text locale="en">"$unit($mage) creates $int($number) $resource($item,$number)."</text>
   </message>
 
   <message name="curseinfo::magicrunes_ship" section="magic">
@@ -7904,8 +6096,6 @@
       <arg name="ship" type="ship"/>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"Auf den Planken von $ship($ship) erkennt man seltsame Runen. ($int36($id))"</text>
-    <text locale="en">"The plank of $ship($ship) are inscribed with strange runes. ($int36($id))"</text>
   </message>
 
   <message name="disrupt_astral" section="magic">
@@ -7913,8 +6103,6 @@
       <arg name="unit" type="unit"/>
       <arg name="region" type="region"/>
     </type>
-    <text locale="de">"$unit($unit) wird aus der astralen Ebene nach $region($region) geschleudert."</text>
-    <text locale="en">"$unit($unit) is sent from the astral plain to $region($region)."</text>
   </message>
 
   <message name="send_astral" section="magic">
@@ -7922,8 +6110,6 @@
       <arg name="unit" type="unit"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($target) wird von $unit($unit) in eine andere Welt geschleudert."</text>
-    <text locale="en">"$unit($unit) sends $unit($target) to another world."</text>
   </message>
 
   <message name="try_astral" section="magic">
@@ -7931,16 +6117,12 @@
       <arg name="unit" type="unit"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) versuchte erfolglos, $unit($target) in eine andere Welt zu schleudern."</text>
-    <text locale="en">"$unit($unit) tried but failed to send $unit($target) to another world."</text>
   </message>
 
   <message name="renumber_inuse" section="errors">
     <type>
       <arg name="id" type="int"/>
     </type>
-    <text locale="de">"NUMMER PARTEI $int36($id): Diese Nummer wird von einer anderen Partei benutzt."</text>
-    <text locale="en">"NUMBER FACTION $int36($id): This number is being used by another faction."</text>
   </message>
 
   <message name="mail_result" section="events">
@@ -7948,21 +6130,15 @@
       <arg name="unit" type="unit"/>
       <arg name="message" type="string"/>
     </type>
-    <text locale="de">"Eine Botschaft von $unit($unit): '$message'"</text>
-    <text locale="en">"A message from $unit($unit): '$message'"</text>
   </message>
 
   <message name="mob_warning" section="events">
-    <text locale="de">"Ein Bauernmob erhebt sich und macht Jagd auf Schwarzmagier."</text>
-    <text locale="en">"An angry mob forms and hunts practitioners of the dark arts."</text>
   </message>
 
   <message name="familiar_name" section="events">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"Vertrauter von $unit($unit)"</text>
-    <text locale="en">"Familiar of $unit($unit)"</text>
   </message>
 
   <message name="recruit_archetype" section="events">
@@ -7971,37 +6147,27 @@
       <arg name="archetype" type="string"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) rekrutiert $int($amount) $localize($archetype)."</text>
-    <text locale="en">"$unit($unit) recruits $int($amount) $localize($archetype)."</text>
   </message>
 
   <message name="illegal_password" section="events">
     <type>
       <arg name="newpass" type="string"/>
     </type>
-    <text locale="de">"Dein Passwort enthält Zeichen, die bei der Nachsendung von Reports Probleme bereiten können. Bitte beachte, dass Passwortenur aus Buchstaben von A bis Z und Zahlen bestehen dürfen. Dein neues Passwort ist '${newpass}'."</text>
-    <text locale="en">"Your password was changed because it contained illegal characters. Legal passwords may only contain numbers and letters from A to Z. Your new Password is '${newpass}'."</text>
   </message>
 
   <message name="meow" section="events">
-    <text locale="de">"Miiauuuuuu..."</text>
-    <text locale="en">"Meeoooooow..."</text>
   </message>
 
   <message name="arena_leave_fail" section="events">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"Der Versuch, die Greifenschwingen zu benutzen, schlug fehl. $unit($unit) konnte die Ebene der Herausforderung nicht verlassen."</text>
-    <text locale="en">"The attempt to use wings of the gryphon failed. $unit($unit) could not leave the Plane of Challenge."</text>
   </message>
 
   <message name="caldera_handle_0" section="events">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) springt in die ewigen Feuer des Kraters."</text>
-    <text locale="en">"$unit($unit) jumps into the eternal flame of the caldera."</text>
   </message>
 
   <message name="caldera_handle_1" section="events">
@@ -8009,8 +6175,6 @@
       <arg name="unit" type="unit"/>
       <arg name="items" type="items"/>
     </type>
-    <text locale="de">"$unit($unit) springt in die ewigen Feuer des Kraters."</text>
-    <text locale="en">"$unit($unit) jumps into the eternal flame of the caldera."</text>
   </message>
 
   <message name="arena_enter_fail" section="events">
@@ -8018,8 +6182,6 @@
       <arg name="region" type="region"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"In $region($region) erklingt die Stimme des Torwächters: 'Nur wer ohne materielle Güter und noch lernbegierig ist, der darf die Ebene der Herausforderung betreten. Und vergiß nicht mein Trinkgeld.'. $unit($unit) erhielt keinen Einlaß."</text>
-    <text locale="en">"$region($region) reverberates from the voice of the gate keeper: 'Only those who forgo material riches and who are willing to learn my enter the Plane of Challenge. And don't forget about my tip!'. $unit($unit) was not admitted."</text>
   </message>
 
   <message name="arena_enter" section="events">
@@ -8027,16 +6189,12 @@
       <arg name="region" type="region"/>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"In $region($region) öffnet sich ein Portal. Eine Stimme ertönt, und spricht: 'Willkommen in der Ebene der Herausforderung'. $unit($unit) durchschreitet das Tor zu einer anderen Welt."</text>
-    <text locale="en">"A portal opens in $region($region). A voice calls: 'Welcome to the Plane of Challenge'. $unit($unit) walks through the gate to another world."</text>
   </message>
 
   <message name="chaos_disease" section="events">
     <type>
       <arg name="unit" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) scheint von einer seltsamen Krankheit befallen."</text>
-    <text locale="en">"$unit($unit) is stricken by a strange disease."</text>
   </message>
 
   <message name="battle_loot" section="battle">
@@ -8045,8 +6203,6 @@
       <arg name="amount" type="int"/>
       <arg name="item" type="resource"/>
     </type>
-    <text locale="de">"$unit($unit) erbeutet $int($amount) $resource($item,$amount)."</text>
-    <text locale="en">"$unit($unit) collects $int($amount) $resource($item,$amount)."</text>
   </message>
 
   <message name="peace_active" section="battle">
@@ -8055,9 +6211,6 @@
       <arg name="unit" type="unit"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es ist so schön friedlich, man möchte hier niemanden angreifen."</text>  
-    <text locale="en">"$unit($unit) in $region($region):
-    '$order($command)' - It is so quiet and peaceful, nobody wants to attack anybody right now."</text>
   </message>
 
   <message name="error_race_nolearn" section="errors">
@@ -8067,8 +6220,6 @@
       <arg name="command" type="order"/>
       <arg name="race" type="race"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) können nichts lernen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $race($race,0) cannot study."</text>
   </message>
 
   <message name="error_migrants_nolearn" section="errors">
@@ -8077,8 +6228,6 @@
       <arg name="unit" type="unit"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Migranten können keine kostenpflichtigen Talente lernen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Migrants cannot study this."</text>
   </message>
 
   <message name="error_max_magicians" section="errors">
@@ -8088,8 +6237,6 @@
       <arg name="command" type="order"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es kann maximal $int($amount) Magier pro Partei geben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There may not be more than $int($amount) magicians in your faction."</text>
   </message>
 
   <message name="error_max_alchemists" section="errors">
@@ -8099,8 +6246,6 @@
       <arg name="command" type="order"/>
       <arg name="amount" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Es kann maximal $int($amount) Alchemisten pro Partei geben."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - There may not be more tha $int($amount) alchemists in your faction."</text>
   </message>
 
   <message name="error_different_magic" section="errors">
@@ -8110,8 +6255,6 @@
       <arg name="command" type="order"/>
       <arg name="target" type="unit"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - $unit($target) versteht unsere Art von Magie nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - $unit($target) does not understand our kind of magic."</text>
   </message>
 
   <message name="error_captain_skill_low" section="errors">
@@ -8122,8 +6265,6 @@
       <arg name="value" type="int"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Der Kapitän muß ein Segeltalent von mindestens $int($value) haben, um $ship($ship) zu befehligen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The captain needs a sailing skill of at least $int($value), to command $ship($ship)."</text>
   </message>
 
   <message name="error_roads_finished" section="errors">
@@ -8132,8 +6273,6 @@
       <arg name="unit" type="unit"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - In dieser Richtung gibt es keine Brücken und Straßen mehr zu bauen."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - The roads and bridges in that direction are complete."</text>
   </message>
 
   <message name="error_build_skill_low" section="errors">
@@ -8143,8 +6282,6 @@
       <arg name="command" type="order"/>
       <arg name="value" type="int"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Um das zu bauen, braucht man ein Talent von mindestens $int($value)."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This requires a skill of at least $int($value) to build."</text>
   </message>
 
   <message name="slave_active" section="battle">
@@ -8153,8 +6290,6 @@
       <arg name="unit" type="unit"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Diese Einheit kämpft nicht."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This unit will not fight."</text>
   </message>
 
   <message name="harbor_trade" section="events">
@@ -8163,8 +6298,6 @@
       <arg name="items" type="items"/>
       <arg name="ship" type="ship"/>
     </type>
-    <text locale="de">"$unit($unit) erhielt $resources($items) von der $ship($ship)."</text>
-    <text locale="en">"$unit($unit) received $resources($items) from the $ship($ship)."</text>
   </message>
   
   <message name="error_not_on_undead" section="errors">
@@ -8173,8 +6306,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Dieser Zauber kann nicht auf Untote gezaubert werden."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - This spell cannot be cast upon undead."</text>
   </message>
   
   <message name="warn_dropout" section="errors">
@@ -8182,11 +6313,6 @@
       <arg name="faction" type="faction"/>
       <arg name="turns" type="int"/>
     </type>
-    <text locale="de">"Achtung: $faction($faction) hat seit $int($turns) Wochen keine
-    Züge eingeschickt und könnte dadurch in Kürze aus dem Spiel
-    ausscheiden."</text>
-    <text locale="en">"Warning: $faction($faction) has not been sending in
-    orders for $int($turns) turns and may be leaving the game soon."</text>
   </message>
 
   <message name="error_herorecruit" section="errors">
@@ -8195,8 +6321,6 @@
       <arg name="region" type="region"/>
       <arg name="command" type="order"/>
     </type>
-    <text locale="de">"$unit($unit) in $region($region): '$order($command)' - Helden können nicht rekrutieren."</text>
-    <text locale="en">"$unit($unit) in $region($region): '$order($command)' - Heroes cannot recruit."</text>
   </message>
 
   <message name="dragon_growl" section="mail">
@@ -8206,8 +6330,6 @@
       <arg name="target" type="region"/>
       <arg name="growl" type="string"/>
     </type>
-    <text locale="de">"$unit($dragon): \"$localize($growl) $if($eq($number,1), "Ich rieche", "Wir riechen") etwas in $region($target)\"."</text>
-    <text locale="en">"$unit($dragon): \"$localize($growl) $if($eq($number,1), "I smell", "We smell") something in $region($target)\"."</text>
   </message>
 
 </messages>
diff --git a/src/exparse.c b/src/exparse.c
index 271443c05..dfba3f5d0 100644
--- a/src/exparse.c
+++ b/src/exparse.c
@@ -355,7 +355,7 @@ static void start_messages(parseinfo *pi, const XML_Char *el, const XML_Char **a
             pi->object = mt_new(name, section);
         }
     }
-    else if (xml_strcmp(el, "type") != 0 && xml_strcmp(el, "text") != 0) {
+    else if (xml_strcmp(el, "type") != 0) {
         handle_bad_input(pi, el, NULL);
     }
 }

From 22f6d4feed230edaa505ea149cff4b9289b5d278 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 18 May 2018 21:36:10 +0200
Subject: [PATCH 56/59] fix sections handling, remove it from nrmessage.

---
 src/util/message.c   | 42 +++++++++++++++++++++++++++++++++++++++++-
 src/util/message.h   |  3 +++
 src/util/nrmessage.c | 36 ------------------------------------
 src/util/nrmessage.h |  3 ---
 4 files changed, 44 insertions(+), 40 deletions(-)

diff --git a/src/util/message.c b/src/util/message.c
index b01993098..64c161d24 100644
--- a/src/util/message.c
+++ b/src/util/message.c
@@ -122,6 +122,42 @@ message_type *mt_create(message_type * mtype, const char *args[], int nparameter
     return mtype;
 }
 
+char *sections[MAXSECTIONS];
+
+const char *section_find(const char *name)
+{
+    int i;
+
+    if (name == NULL) {
+        return NULL;
+    }
+
+    for (i = 0; i != MAXSECTIONS && sections[i]; ++i) {
+        if (strcmp(sections[i], name) == 0) {
+            return sections[i];
+        }
+    }
+    return NULL;
+}
+
+const char *section_add(const char *name) {
+    int i;
+    if (name == NULL) {
+        return NULL;
+    }
+    for (i = 0; i != MAXSECTIONS && sections[i]; ++i) {
+        if (strcmp(sections[i], name) == 0) {
+            return sections[i];
+        }
+    }
+    assert(i < MAXSECTIONS);
+    assert(sections[i] == NULL);
+    if (i + 1 < MAXSECTIONS) {
+        sections[i + 1] = NULL;
+    }
+    return sections[i] = str_strdup(name);
+}
+
 message_type *mt_new(const char *name, const char *section)
 {
     message_type *mtype;
@@ -134,7 +170,10 @@ message_type *mt_new(const char *name, const char *section)
     mtype = (message_type *)malloc(sizeof(message_type));
     mtype->key = 0;
     mtype->name = str_strdup(name);
-    mtype->section = section;
+    mtype->section = section_find(section);
+    if (!mtype->section) {
+        mtype->section = section_add(section);
+    }
     mtype->nparameters = 0;
     mtype->pnames = NULL;
     mtype->types = NULL;
@@ -267,3 +306,4 @@ void message_done(void) {
         free(at);
     }
 }
+
diff --git a/src/util/message.h b/src/util/message.h
index 40cc09086..5aa16232b 100644
--- a/src/util/message.h
+++ b/src/util/message.h
@@ -20,6 +20,9 @@ extern "C" {
 
 #define MSG_MAXARGS 8
 #define MT_NEW_END ((const char *)0)
+#define MAXSECTIONS 16
+
+    extern char *sections[MAXSECTIONS];
 
     typedef struct arg_type {
         struct arg_type *next;
diff --git a/src/util/nrmessage.c b/src/util/nrmessage.c
index 047d3565b..1fdde6935 100644
--- a/src/util/nrmessage.c
+++ b/src/util/nrmessage.c
@@ -65,42 +65,6 @@ static nrmessage_type *nrt_find(const struct message_type * mtype)
     return found;
 }
 
-char *sections[MAXSECTIONS];
-
-const char *section_find(const char *name)
-{
-    int i;
-
-    if (name == NULL) {
-        return NULL;
-    }
-
-    for (i = 0; i != MAXSECTIONS && sections[i]; ++i) {
-        if (strcmp(sections[i], name) == 0) {
-            return sections[i];
-        }
-    }
-    return NULL;
-}
-
-const char *section_add(const char *name) {
-    int i;
-    if (name == NULL) {
-        return NULL;
-    }
-    for (i = 0; i != MAXSECTIONS && sections[i]; ++i) {
-        if (strcmp(sections[i], name) == 0) {
-            return sections[i];
-        }
-    }
-    assert(i < MAXSECTIONS);
-    assert(sections[i] == NULL);
-    if (i + 1 < MAXSECTIONS) {
-        sections[i + 1] = NULL;
-    }
-    return sections[i] = str_strdup(name);
-}
-
 void
 nrt_register(const struct message_type *mtype)
 {
diff --git a/src/util/nrmessage.h b/src/util/nrmessage.h
index c0d9257aa..15914841b 100644
--- a/src/util/nrmessage.h
+++ b/src/util/nrmessage.h
@@ -25,9 +25,6 @@ extern "C" {
     struct message_type;
     struct nrmessage_type;
 
-#define MAXSECTIONS 8
-    extern char *sections[MAXSECTIONS];
-
     void free_nrmesssages(void);
 
     void nrt_register(const struct message_type *mtype);

From 33a6d7fa0ed9028e801999d9314f08805237af5a Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 18 May 2018 21:40:26 +0200
Subject: [PATCH 57/59] free sections memory.

---
 src/kernel/config.c | 1 +
 src/util/message.c  | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/src/kernel/config.c b/src/kernel/config.c
index 8eef66341..ff2457971 100644
--- a/src/kernel/config.c
+++ b/src/kernel/config.c
@@ -561,6 +561,7 @@ void kernel_done(void)
     curses_done();
     crmessage_done();
     translation_done();
+    mt_clear();
 }
 
 bool rule_stealth_other(void)
diff --git a/src/util/message.c b/src/util/message.c
index 64c161d24..8915dca8f 100644
--- a/src/util/message.c
+++ b/src/util/message.c
@@ -255,6 +255,10 @@ void mt_clear(void) {
         selist_free(ql);
         messagetypes[i] = 0;
     }
+    for (i = 0; i != MAXSECTIONS && sections[i]; ++i) {
+        free(sections[i]);
+        sections[i] = NULL;
+    }
 }
 
 const message_type *mt_find(const char *name)

From 6699e8940ec6b7ea664a86b664a175c0689e580b Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 18 May 2018 21:44:03 +0200
Subject: [PATCH 58/59] some cleanup is good.

---
 src/eressea.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/eressea.c b/src/eressea.c
index bdb20edcc..982dfe6ee 100644
--- a/src/eressea.c
+++ b/src/eressea.c
@@ -53,9 +53,9 @@ void game_done(void)
     free_config();
     free_special_directions();
     free_locales();
+#endif
     kernel_done();
     dblib_close();
-#endif
 }
 
 void game_init(void)

From adfc4ad7ce9e2ae2bad77a0a34e7c7c4b267a6e1 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno.rehling@gmail.com>
Date: Fri, 18 May 2018 21:54:46 +0200
Subject: [PATCH 59/59] add a header to po files, charset UTF-8

---
 .gitignore                        |  1 +
 res/translations/messages.de.po   | 13 +++++++++++++
 res/translations/messages.en.po   | 13 +++++++++++++
 res/translations/strings-e3.de.po | 13 +++++++++++++
 res/translations/strings-e3.en.po | 13 +++++++++++++
 res/translations/strings.de.po    | 13 +++++++++++++
 res/translations/strings.en.po    | 13 +++++++++++++
 7 files changed, 79 insertions(+)

diff --git a/.gitignore b/.gitignore
index d7c102f5a..d5e8e1b10 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,3 +42,4 @@ tests/data/185.dat
 /quicklist/
 /cutest/
 /critbit/
+*.mo
diff --git a/res/translations/messages.de.po b/res/translations/messages.de.po
index 8e882a435..98800fd31 100644
--- a/res/translations/messages.de.po
+++ b/res/translations/messages.de.po
@@ -1,3 +1,16 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: de\n"
+"X-Generator: Poedit 2.0.7\n"
+
 msgid "homestone_effect"
 msgstr "\"Mit einem Ritual bindet $unit($mage) die magischen Kräfte der Erde in die Mauern von $building($building).\""
 
diff --git a/res/translations/messages.en.po b/res/translations/messages.en.po
index 558b75ee9..9f11a6312 100644
--- a/res/translations/messages.en.po
+++ b/res/translations/messages.en.po
@@ -1,3 +1,16 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: en\n"
+"X-Generator: Poedit 2.0.7\n"
+
 msgid "homestone_effect"
 msgstr "\"A magic ritual by $unit($mage) binds magic energies to the walls of $building($building).\""
 
diff --git a/res/translations/strings-e3.de.po b/res/translations/strings-e3.de.po
index 2652d9436..71e9363f9 100644
--- a/res/translations/strings-e3.de.po
+++ b/res/translations/strings-e3.de.po
@@ -1,3 +1,16 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: de\n"
+"X-Generator: Poedit 2.0.7\n"
+
 msgid "catamaran_a"
 msgstr "ein Katamaran"
 
diff --git a/res/translations/strings-e3.en.po b/res/translations/strings-e3.en.po
index 169a80a68..311abcf40 100644
--- a/res/translations/strings-e3.en.po
+++ b/res/translations/strings-e3.en.po
@@ -1,3 +1,16 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: en\n"
+"X-Generator: Poedit 2.0.7\n"
+
 msgid "catamaran_a"
 msgstr "a catamaran"
 
diff --git a/res/translations/strings.de.po b/res/translations/strings.de.po
index d739a0b6d..b7881b3f8 100644
--- a/res/translations/strings.de.po
+++ b/res/translations/strings.de.po
@@ -1,3 +1,16 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: de\n"
+"X-Generator: Poedit 2.0.7\n"
+
 msgid "rustychainmail"
 msgstr "Rostiges Kettenhemd"
 
diff --git a/res/translations/strings.en.po b/res/translations/strings.en.po
index 1e2dfdb1a..774874bf1 100644
--- a/res/translations/strings.en.po
+++ b/res/translations/strings.en.po
@@ -1,3 +1,16 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: en\n"
+"X-Generator: Poedit 2.0.7\n"
+
 msgid "rustychainmail"
 msgstr "rustychainmail"