From e93628434738d36a4564ebb020d2ba414526c628 Mon Sep 17 00:00:00 2001
From: Enno Rehling <enno@eressea.de>
Date: Sat, 11 Feb 2006 16:11:16 +0000
Subject: [PATCH] Massive changes:

- removed all hadcoded weapons
- added code to put resources like iron&wood in XML
- added laen & wood to XML
- fixed damage for mallorn lance
- removed the old entrise code
- added new ent code in lua, eressea-only
---
 src/common/gamecode/economy.c     | 383 ++++++++++++++----------------
 src/common/gamecode/economy.h     |   1 -
 src/common/gamecode/randenc.c     | 131 +---------
 src/common/items/seed.c           |   4 +-
 src/common/items/weapons.c        |  23 +-
 src/common/kernel/alchemy.c       |   4 +-
 src/common/kernel/building.c      |  23 +-
 src/common/kernel/building.h      |  10 +-
 src/common/kernel/eressea.c       |   1 -
 src/common/kernel/give.c          |   2 -
 src/common/kernel/item.c          | 203 +++++-----------
 src/common/kernel/item.h          |  43 ++--
 src/common/kernel/movement.c      | 115 +++++----
 src/common/kernel/region.c        |  22 +-
 src/common/kernel/region.h        |   2 -
 src/common/kernel/xmlreader.c     | 205 +++++++++++-----
 src/common/modules/arena.c        |  15 +-
 src/common/modules/autoseed.c     |  15 +-
 src/common/modules/gmcmd.c        |   8 +-
 src/common/settings-eressea.h     |   1 -
 src/common/settings-tutorial.h    |   1 -
 src/common/settings-vinyambar-3.h |   1 -
 src/common/settings-wdw.h         |   1 -
 src/eressea/korrektur.c           |   2 +-
 src/eressea/lua/eressea.cpp       |   5 +-
 src/eressea/lua/item.cpp          |  55 ++++-
 src/eressea/main.c                |   1 -
 src/eressea/server.cpp            |   1 -
 src/mapper/map_partei.c           |  27 ---
 src/res/equipment.xml             |  11 +
 src/res/messages.xml              |  10 +
 src/res/resources.xml             |  99 +++++++-
 src/scripts/eressea.lua           |   4 +-
 src/scripts/eressea/ents.lua      |  33 +++
 src/scripts/extensions.lua        |  46 ++++
 35 files changed, 753 insertions(+), 755 deletions(-)
 create mode 100644 src/scripts/eressea/ents.lua

diff --git a/src/common/gamecode/economy.c b/src/common/gamecode/economy.c
index b98a6c850..41d21057f 100644
--- a/src/common/gamecode/economy.c
+++ b/src/common/gamecode/economy.c
@@ -484,11 +484,7 @@ recruit(unit * u, struct order * ord, request ** recruitorders)
 	}
 
   if (!(rc->ec_flags & ECF_REC_HORSES) && fval(r, RF_ORCIFIED)) {
-#if RACE_ADJUSTMENTS
     if (rc != new_race[RC_URUK])
-#else
-    if (rc != new_race[RC_ORC])
-#endif
     {
       cmistake(u, ord, 238, MSG_EVENT);
       return;
@@ -1164,6 +1160,20 @@ typedef struct allocation_list {
 
 static allocation_list * allocations;
 
+static boolean
+can_guard(const unit * guard, const unit * u)
+{
+  if (fval(guard, UFL_ISNEW)) return false;
+  if (guard->number<=0 || !cansee(guard->faction, guard->region, u, 0)) return false;
+  if (besieged(guard) || !armedmen(guard)) return false;
+
+  return !alliedunit(guard, u->faction, HELP_GUARD);
+}
+
+enum {
+  AFL_DONE = 1<<0,
+  AFL_LOWSKILL = 1<<1
+};
 
 static void
 allocate_resource(unit * u, const resource_type * rtype, int want)
@@ -1174,22 +1184,25 @@ allocate_resource(unit * u, const resource_type * rtype, int want)
 	int dm = 0;
 	allocation_list * alist;
 	allocation * al;
-	unit *u2;
-	int amount, skill;
+  attrib * a = a_find(rtype->attribs, &at_resourcelimit);
+  resource_limit * rdata = (resource_limit*)a->data.v;
+  int amount, skill;
 
 	/* momentan kann man keine ressourcen abbauen, wenn man daf�r
 	* Materialverbrauch hat: */
 	assert(itype!=NULL && (itype->construction==NULL || itype->construction->materials==NULL));
+  assert(rdata!=NULL);
 
-	if (itype == olditemtype[I_WOOD] && fval(r, RF_MALLORN)) {
-		cmistake(u, u->thisorder, 92, MSG_PRODUCE);
-		return;
-	}
-	if (itype == olditemtype[I_MALLORN] && !fval(r, RF_MALLORN)) {
-		cmistake(u, u->thisorder, 91, MSG_PRODUCE);
-		return;
-	}
-	if (itype == olditemtype[I_LAEN]) {
+  if (rdata->limit!=NULL) {
+    int avail = rdata->limit(r, rtype);
+    if (avail<=0) {
+      cmistake(u, u->thisorder, 121, MSG_PRODUCE);
+      return;
+    }
+
+  }
+
+  if (itype == olditemtype[I_LAEN]) {
 		struct building * b = inside_building(u);
 		const struct building_type * btype = b?b->type:NULL;
 		if (btype != bt_find("mine")) {
@@ -1202,21 +1215,15 @@ allocate_resource(unit * u, const resource_type * rtype, int want)
 		cmistake(u, u->thisorder, 60, MSG_PRODUCE);
 		return;
 	}
-	/* Elfen k�nnen Holzf�llen durch Bewachen verhindern, wenn sie
-	die Holzf�ller sehen. */
-	if (itype == olditemtype[I_WOOD] || itype == olditemtype[I_MALLORN]) {
+
+  if (rdata->guard!=0) {
+    unit * u2;
 		for (u2 = r->units; u2; u2 = u2->next) {
-			if (getguard(u2) & GUARD_TREES
-				&& u2->number
-				&& cansee(u2->faction,r,u,0)
-				&& !besieged(u2)
-				&& !alliedunit(u2, u->faction, HELP_GUARD)
-				&& armedmen(u2)
-				) {
-					ADDMSG(&u->faction->msgs,
-						msg_feedback(u, u->thisorder, "region_guarded", "guard", u2));
-					return;
-				}
+			if ((getguard(u2) & rdata->guard) && can_guard(u2, u)) {
+        ADDMSG(&u->faction->msgs,
+          msg_feedback(u, u->thisorder, "region_guarded", "guard", u2));
+        return;
+      }
 		}
 	}
 
@@ -1224,8 +1231,8 @@ allocate_resource(unit * u, const resource_type * rtype, int want)
 	* Als magische Wesen 'sehen' Bergw�chter alles und werden durch
 	* Belagerung nicht aufgehalten.  (Ansonsten wie oben bei Elfen anpassen).
 	*/
-	if (itype == olditemtype[I_IRON] || itype == olditemtype[I_LAEN])
-	{
+	if (itype == olditemtype[I_IRON] || itype == olditemtype[I_LAEN]) {
+    unit * u2;
 		for (u2 = r->units; u2; u2 = u2->next ) {
 			if (getguard(u) & GUARD_MINING
 				&& !fval(u2, UFL_ISNEW)
@@ -1256,18 +1263,24 @@ allocate_resource(unit * u, const resource_type * rtype, int want)
 	} else {
 		struct building * b = inside_building(u);
 		const struct building_type * btype = b?b->type:NULL;
-		if (itype == olditemtype[I_IRON] && btype == bt_find("mine")) {
+
+    if (rdata->modifiers) {
+      resource_mod * mod = rdata->modifiers;
+      for (;mod->flags!=0;++mod) {
+        if (mod->flags & RMF_SKILL) {
+          if (mod->btype==NULL || mod->btype==btype) {
+            if (mod->race==NULL || mod->race==u->race) {
+              skill += mod->value.i;
+            }
+          }
+        }
+      }
+    } else if (itype == olditemtype[I_IRON] && btype == bt_find("mine")) {
 			++skill;
 		}
 		else if (itype == olditemtype[I_STONE] && btype == bt_find("quarry")) {
 			++skill;
 		}
-		else if (itype == olditemtype[I_WOOD] && btype == bt_find("sawmill")) {
-			++skill;
-		}
-		else if (itype == olditemtype[I_MALLORN] && btype == bt_find("sawmill")) {
-			++skill;
-		}
 	}
 	amount = skill * u->number;
 	/* nun ist amount die Gesamtproduktion der Einheit (in punkten) */
@@ -1303,193 +1316,168 @@ allocate_resource(unit * u, const resource_type * rtype, int want)
 	al->next = alist->data;
 	al->unit = u;
 	alist->data = al;
-	if (itype==olditemtype[I_IRON]) {
+
+  if (rdata->modifiers) {
+    struct building * b = inside_building(u);
+    const struct building_type * btype = b?b->type:NULL;
+
+    resource_mod * mod = rdata->modifiers;
+    for (;mod->flags!=0;++mod) {
+      if (mod->flags & RMF_SKILL) {
+        if (mod->btype==NULL || mod->btype==btype) {
+          if (mod->race==NULL || mod->race==u->race) {
+            al->save *= mod->value.f;
+          }
+        }
+      }
+    }
+  } else if (itype==olditemtype[I_IRON]) {
 		struct building * b = inside_building(u);
 		const struct building_type * btype = b?b->type:NULL;
 		if (btype==bt_find("mine"))
 			al->save *= 0.5;
 		if (u->race == new_race[RC_DWARF]) {
-#if RACE_ADJUSTMENTS
 			al->save *= 0.75;
-#else
-			al->save *= 0.5;
-#endif
 		}
 	} else if (itype==olditemtype[I_STONE]) {
 		struct building * b = inside_building(u);
 		const struct building_type * btype = b?b->type:NULL;
 		if (btype==bt_find("quarry"))
 			al->save = al->save*0.5;
-#if RACE_ADJUSTMENTS
 		if (u->race == new_race[RC_TROLL])
 			al->save = al->save*0.75;
-#endif
-	} else if (itype==olditemtype[I_MALLORN]) {
-		struct building * b = inside_building(u);
-		const struct building_type * btype = b?b->type:NULL;
-		if (btype==bt_find("sawmill"))
-			al->save *= 0.5;
-	} else if (itype==olditemtype[I_WOOD]) {
-		struct building * b = inside_building(u);
-		const struct building_type * btype = b?b->type:NULL;
-		if (btype==bt_find("sawmill"))
-			al->save *= 0.5;
 	}
 }
 
-typedef struct allocator {
-	const struct resource_type * type;
-	void (*allocate)(const struct allocator *, region *, allocation *);
-
-	struct allocator * next;
-} allocator;
-
-static struct allocator * allocators;
-
-static const allocator *
-get_allocator(const struct resource_type * type)
-{
-	const struct allocator * alloc = allocators;
-	while (alloc && alloc->type!=type) alloc = alloc->next;
-	return alloc;
-}
-
-static allocator *
-make_allocator(const struct resource_type * type, void (*allocate)(const struct allocator *, region *, allocation *))
-{
-	allocator * alloc = (allocator *)malloc(sizeof(allocator));
-	alloc->type = type;
-	alloc->allocate = allocate;
-	return alloc;
-}
-
-static void
-add_allocator(allocator * alloc)
-{
-	alloc->next = allocators;
-	allocators = alloc;
-}
-
-enum {
-	AFL_DONE = 1<<0,
-	AFL_LOWSKILL = 1<<1
-};
-
 static int
 required(int want, double save)
 {
-	int norders = (int)(want * save);
-	if (norders < want*save) ++norders;
-	return norders;
+  int norders = (int)(want * save);
+  if (norders < want*save) ++norders;
+  return norders;
 }
 
 static void
-leveled_allocation(const allocator * self, region * r, allocation * alist)
+leveled_allocation(const resource_type * rtype, region * r, allocation * alist)
 {
-	const resource_type * rtype = self->type;
-	const item_type * itype = resource2item(rtype);
-	rawmaterial * rm = rm_get(r, rtype);
-	int need;
-	boolean first = true;
+  const item_type * itype = resource2item(rtype);
+  rawmaterial * rm = rm_get(r, rtype);
+  int need;
+  boolean first = true;
 
-	if (rm!=NULL) {
-		do {
-			int avail = rm->amount;
-			int norders = 0;
-			allocation * al;
+  if (rm!=NULL) {
+    do {
+      int avail = rm->amount;
+      int norders = 0;
+      allocation * al;
 
-			if(avail <= 0) {
-				for (al=alist;al;al=al->next) {
-					al->get = 0;
-				}
-				break;
-			}
+      if(avail <= 0) {
+        for (al=alist;al;al=al->next) {
+          al->get = 0;
+        }
+        break;
+      }
 
-			assert(avail>0);
+      assert(avail>0);
 
-			for (al=alist;al;al=al->next) if (!fval(al, AFL_DONE)) {
-				int req = required(al->want-al->get, al->save);
-				assert(al->get<=al->want && al->get >= 0);
-				if (eff_skill(al->unit, itype->construction->skill, r)
-					>= rm->level+itype->construction->minskill-1) {
-						if (req) {
-							norders += req;
-						} else {
-							fset(al, AFL_DONE);
-						}
-					} else {
-						fset(al, AFL_DONE);
-						if (first) fset(al, AFL_LOWSKILL);
-					}
-			}
-			need = norders;
+      for (al=alist;al;al=al->next) if (!fval(al, AFL_DONE)) {
+        int req = required(al->want-al->get, al->save);
+        assert(al->get<=al->want && al->get >= 0);
+        if (eff_skill(al->unit, itype->construction->skill, r)
+          >= rm->level+itype->construction->minskill-1) {
+            if (req) {
+              norders += req;
+            } else {
+              fset(al, AFL_DONE);
+            }
+          } else {
+            fset(al, AFL_DONE);
+            if (first) fset(al, AFL_LOWSKILL);
+          }
+      }
+      need = norders;
 
-			avail = min(avail, norders);
-			if (need>0) {
-				int use = 0;
-				for (al=alist;al;al=al->next) if (!fval(al, AFL_DONE)) {
-					if (avail > 0) {
-						int want = required(al->want-al->get, al->save);
-						int x = avail*want/norders;
-						/* Wenn Rest, dann w�rfeln, ob ich was bekomme: */
-						if (rand() % norders < (avail*want) % norders)
-							++x;
-						avail -= x;
-						use += x;
-						norders -= want;
-						need -= x;
-						al->get = min(al->want, al->get+(int)(x/al->save));
-					}
-				}
-				if (use) {
-					assert(use<=rm->amount);
-					rm->type->use(rm, r, use);
-				}
-				assert(avail==0 || norders==0);
-			}
-			first = false;
-		} while (need>0);
-	}
+      avail = min(avail, norders);
+      if (need>0) {
+        int use = 0;
+        for (al=alist;al;al=al->next) if (!fval(al, AFL_DONE)) {
+          if (avail > 0) {
+            int want = required(al->want-al->get, al->save);
+            int x = avail*want/norders;
+            /* Wenn Rest, dann w�rfeln, ob ich was bekomme: */
+            if (rand() % norders < (avail*want) % norders)
+              ++x;
+            avail -= x;
+            use += x;
+            norders -= want;
+            need -= x;
+            al->get = min(al->want, al->get+(int)(x/al->save));
+          }
+        }
+        if (use) {
+          assert(use<=rm->amount);
+          rm->type->use(rm, r, use);
+        }
+        assert(avail==0 || norders==0);
+      }
+      first = false;
+    } while (need>0);
+  }
 }
 
 static void
-attrib_allocation(const allocator * self, region * r, allocation * alist)
+attrib_allocation(const resource_type * rtype, region * r, allocation * alist)
 {
-	allocation * al;
-	const resource_type * rtype = self->type;
-	int avail = 0;
-	int norders = 0;
-	attrib * a = a_find(rtype->attribs, &at_resourcelimit);
-	resource_limit * rdata = (resource_limit*)a->data.v;
+  allocation * al;
+  int norders = 0;
+  attrib * a = a_find(rtype->attribs, &at_resourcelimit);
+  resource_limit * rdata = (resource_limit*)a->data.v;
+  int avail = rdata->value;
 
-	for (al=alist;al;al=al->next) {
-		norders += required(al->want, al->save);
-	}
+  for (al=alist;al;al=al->next) {
+    norders += required(al->want, al->save);
+  }
 
-	if (rdata->limit) {
-		avail = rdata->limit(r, rtype);
-		if (avail < 0) avail = 0;
-	}
-	else avail = rdata->value;
+  if (rdata->limit) {
+    avail = rdata->limit(r, rtype);
+    if (avail < 0) avail = 0;
+  }
 
-	avail = min(avail, norders);
-	for (al=alist;al;al=al->next) {
-		if (avail > 0) {
-			int want = required(al->want, al->save);
-			int x = avail*want/norders;
-			/* Wenn Rest, dann w�rfeln, ob ich was bekomme: */
-			if (rand() % norders < (avail*want) % norders)
-				++x;
-			avail -= x;
-			norders -= want;
-			al->get = min(al->want, (int)(x/al->save));
-			if (rdata->use) {
-				int use = required(al->get, al->save);
-				if (use) rdata->use(r, rtype, use);
-			}
-		}
-	}
-	assert(avail==0 || norders==0);
+  avail = min(avail, norders);
+  for (al=alist;al;al=al->next) {
+    if (avail > 0) {
+      int want = required(al->want, al->save);
+      int x = avail*want/norders;
+      /* Wenn Rest, dann w�rfeln, ob ich was bekomme: */
+      if (rand() % norders < (avail*want) % norders)
+        ++x;
+      avail -= x;
+      norders -= want;
+      al->get = min(al->want, (int)(x/al->save));
+      if (rdata->produce) {
+        int use = required(al->get, al->save);
+        if (use) rdata->produce(r, rtype, use);
+      }
+    }
+  }
+  assert(avail==0 || norders==0);
+}
+
+typedef void (*allocate_function)(const resource_type *, struct region *, struct allocation *);
+
+static allocate_function
+get_allocator(const struct resource_type * rtype)
+{
+  attrib * a = a_find(rtype->attribs, &at_resourcelimit);
+
+  if (a!=NULL) {
+    resource_limit * rdata = (resource_limit*)a->data.v;
+    if (rdata->value>0 || rdata->limit!=NULL) {
+      return attrib_allocation;
+    }
+    return leveled_allocation;
+  }
+  return NULL;
 }
 
 static void
@@ -1500,12 +1488,12 @@ split_allocations(region * r)
 	while (*p_alist) {
 		allocation_list * alist = *p_alist;
 		const resource_type * rtype = alist->type;
-		const allocator * alloc = get_allocator(rtype);
+		allocate_function alloc = get_allocator(rtype);
 		const item_type * itype = resource2item(rtype);
 		allocation ** p_al = &alist->data;
 
 		freset(r, RF_DH);
-		alloc->allocate(alloc, r, alist->data);
+		alloc(rtype, r, alist->data);
 
 		while (*p_al) {
 			allocation * al = *p_al;
@@ -3201,16 +3189,3 @@ produce(void)
 
   }
 }
-
-void
-init_economy(void)
-{
-  add_allocator(make_allocator(item2resource(olditemtype[I_HORSE]), attrib_allocation));
-  add_allocator(make_allocator(item2resource(olditemtype[I_WOOD]), attrib_allocation));
-  add_allocator(make_allocator(item2resource(olditemtype[I_MALLORN]), attrib_allocation));
-  add_allocator(make_allocator(item2resource(olditemtype[I_STONE]), leveled_allocation));
-  add_allocator(make_allocator(item2resource(olditemtype[I_IRON]), leveled_allocation));
-  add_allocator(make_allocator(item2resource(olditemtype[I_LAEN]), leveled_allocation));
-  add_allocator(make_allocator(rt_seed, attrib_allocation));
-  add_allocator(make_allocator(rt_mallornseed, attrib_allocation));
-}
diff --git a/src/common/gamecode/economy.h b/src/common/gamecode/economy.h
index c16cb0035..8570b500d 100644
--- a/src/common/gamecode/economy.h
+++ b/src/common/gamecode/economy.h
@@ -53,7 +53,6 @@ void produce(void);
 enum { IC_WORK, IC_ENTERTAIN, IC_TAX, IC_TRADE, IC_TRADETAX, IC_STEAL, IC_MAGIC };
 void maintain_buildings(boolean crash);
 extern void add_spende(struct faction * f1, struct faction * f2, int betrag, struct region * r);
-extern void init_economy(void);
 
 #ifdef __cplusplus
 }
diff --git a/src/common/gamecode/randenc.c b/src/common/gamecode/randenc.c
index a5e333f57..e2015cb70 100644
--- a/src/common/gamecode/randenc.c
+++ b/src/common/gamecode/randenc.c
@@ -298,24 +298,10 @@ get_unit(region * r, unit * u)
 	newunit = createunit(r, u->faction, rand() % 20 + 3, u->faction->race);
   fset(newunit, UFL_ISNEW|UFL_MOVED);
 	set_string(&newunit->name, "Dorfbewohner");
-	set_money(newunit, (rand() % 26 + 10) * newunit->number);
-	if (fval(u, UFL_PARTEITARNUNG)) fset(newunit, UFL_PARTEITARNUNG);
-	switch (rand() % 4) {
-	case 0:
-		set_level(newunit, SK_MINING, 1);
-		break;
-	case 1:
-		set_level(newunit, SK_LUMBERJACK, 1);
-		break;
-	case 2:
-		set_level(newunit, SK_CARTMAKER, 1);
-		break;
-	case 3:
-		set_level(newunit, SK_QUARRYING, 1);
-		break;
-	}
-	set_item(newunit, I_WAGON, rand() % 2);
-	set_item(newunit, I_HORSE, min(get_item(newunit, I_WAGON) * 2, rand() % 5));
+  if (fval(u, UFL_PARTEITARNUNG)) {
+    fset(newunit, UFL_PARTEITARNUNG);
+  }
+  equip_unit(newunit, get_equipment("random_villagers"));
 }
 
 static void
@@ -1204,77 +1190,6 @@ randomevents(void)
   orc_growth();
   demon_skillchanges();
 
-#if RACE_ADJUSTMENTS == 0
-	/* Orks vermehren sich */
-
-	for (r = regions; r; r = r->next) {
-
-		plane * p = rplane(r);
-		/* there is a flag for planes without orc growth: */
-		if (p && (p->flags & PFL_NOORCGROWTH)) continue;
-		for (u = r->units; u; u = u->next) {
-			if ( (u->race == new_race[RC_ORC])
-					&& !has_skill(u, SK_MAGIC) && !has_skill(u, SK_ALCHEMY)) {
-				int n;
-				int increase = 0;
-				int num  = u->number;
-				int prob = 5;
-
-				for (n = (num - get_item(u, I_CHASTITY_BELT)); n > 0; n--) {
-					if (rand() % 100 < prob) {
-						++increase;
-					}
-        }
-        if (increase) {
-          if (u->race == new_race[RC_ORC]) {
-            int i;
-            struct orcskills {
-              skill_t skill;
-              int level;
-            } skills [] = { 
-              { SK_MELEE, 1 }, { SK_SPEAR, 1 }, { SK_TACTICS, 0 }, 
-              { SK_LONGBOW, 0 }, { SK_CROSSBOW, 0 }, { SK_CATAPULT, 0 }, 
-              { SK_AUSDAUER, 0 }, { NOSKILL, 0 }
-            };
-            for (i=0;skills[i].skill!=NOSKILL;++i) {
-              int k = get_level(u, skills[i].skill);
-              change_skill(u, skills[i].skill, increase * max(k, s));
-            }
-          }
-
-          set_number(u, u->number + increase);
-
-          u->hp += unit_max_hp(u) * increase;
-          ADDMSG(&u->faction->msgs, msg_message("orcgrowth",
-            "unit amount race", u, increase, u->race));
-        }
-          }
-    }
-  }
-#endif
-
-  for (r = regions; r; r = r->next) {
-#if !RACE_ADJUSTMENTS
-    /* Elfen generieren Wald */
-    if (r->land && !fval(r, RF_MALLORN)) {
-      int trees = rtrees(r, 2);
-      int maxgen = (production(r) * MAXPEASANTS_PER_AREA)/8;
-      for (u = r->units; u && maxgen > 0; u = u->next) {
-        if (u->race == new_race[RC_ELF]) {
-          for (n = u->number; n && maxgen > 0; n--) {
-            if (rand() % 1000 < 15) {	/* 1.5% Chance */
-              trees++;
-            }
-            maxgen--;
-          }
-        }
-      }
-      rsettrees(r, 2, trees);
-    } /* !RACE_ADJUSTMENTS */
-#endif
-
-  }
-
   /* Orkifizierte Regionen mutieren und mutieren zur�ck */
 
   for (r = regions; r; r = r->next) {
@@ -1373,45 +1288,7 @@ randomevents(void)
     }
   }
 
-  /* Fr�hling, die B�ume schlagen aus. */
-
-  for (r = regions; r; r = r->next) {
-    if (fval(r, RF_CHAOTIC) ||(r->x >= -13  && r->x <= -6  && r->y >= 50 && r->y <= 57)) {
-      if (woodcount(r) >= 40 && rand()%100 < 33) {
-        int trees = rtrees(r,2);
-        int treemen = rand()%(max(50,trees)/3);
-        struct message * msg;
-
-        treemen = max(25, treemen);
-        woodcounts(r, -40);
-        trees = max(0, trees-treemen);
-        rsettrees(r, 2, trees);
-        u = createunit(r, findfaction(MONSTER_FACTION),treemen, new_race[RC_TREEMAN]);
-        fset(u, UFL_ISNEW|UFL_MOVED);
-
-        set_level(u, SK_OBSERVATION, 2);
-        if (u->number == 1)
-          set_string(&u->name, "Ein w�tender Ent");
-        else
-          set_string(&u->name, "W�tende Ents");
-
-        log_printf("%d Ents in %s.\n", u->number, regionname(r, NULL));
-
-        msg = msg_message("entrise", "region", r);
-        add_message(&r->msgs, msg);
-        for (u=r->units;u;u=u->next) freset(u->faction, FL_DH);
-        for (u=r->units;u;u=u->next) {
-          if (fval(u->faction, FL_DH)) continue;
-          fset(u->faction, FL_DH);
-          add_message(&u->faction->msgs, msg);
-        }
-        msg_release(msg);
-      }
-    }
-  }
-
 	/* Chaos */
-
 	for (r = regions; r; r = r->next) {
 		int i;
 		if (fval(r, RF_CHAOTIC)) {
diff --git a/src/common/items/seed.c b/src/common/items/seed.c
index 2e7c38f71..995cdc71e 100644
--- a/src/common/items/seed.c
+++ b/src/common/items/seed.c
@@ -56,7 +56,7 @@ init_seed(void)
     a = a_add(&rt_seed->attribs, a_new(&at_resourcelimit));
     rdata = (resource_limit*)a->data.v;
     rdata->limit = limit_seeds;
-    rdata->use = produce_seeds;
+    rdata->produce = produce_seeds;
   }
 }
 
@@ -94,6 +94,6 @@ init_mallornseed(void)
     a = a_add(&rt_mallornseed->attribs, a_new(&at_resourcelimit));
     rdata = (resource_limit*)a->data.v;
     rdata->limit = limit_mallornseeds;
-    rdata->use = produce_mallornseeds;
+    rdata->produce = produce_mallornseeds;
   }
 }
diff --git a/src/common/items/weapons.c b/src/common/items/weapons.c
index 7b9292bed..7cf6f2251 100644
--- a/src/common/items/weapons.c
+++ b/src/common/items/weapons.c
@@ -42,9 +42,6 @@ static weapon_mod wm_lance[] = {
 };
 
 enum {
-	WP_EOGSWORD,
-	WP_SPEAR,
-	WP_LANCE,
 	WP_NONE,
 	WP_MAX
 };
@@ -77,15 +74,10 @@ static weapondata weapontable[WP_MAX + 1] =
 /* MagRes, Schaden/Fu�, Schaden/Pferd, Item, Skill, OffMod, DefMod,
  * missile, is_magic */
 {
-	{0.30, "3d6+10", "3d6+10", I_LAENSWORD, SK_MELEE, 1, 1, false, false, { 0, 0}, CUT },
-	/* Speer */
-	{0.00, "1d10+0", "1d12+2", I_SPEAR, SK_SPEAR, 0, 0, false, false, { 0, 0}, PIERCE },
-	/* Lanze */
-	{0.00, "1d5", "2d6+5", I_LANCE, SK_SPEAR, 0, -2, false, false, { 0, 0}, PIERCE },
 	/* Unbewaffnet */
-	{0.00, "1d5+0", "1d6+0", I_WOOD, SK_MELEE, 0, 0, false, false, { 0, 0}, BASH },
+	{0.00, "1d5+0", "1d6+0", MAX_ITEMS, SK_MELEE, 0, 0, false, false, { 0, 0}, BASH },
 	/* Dummy */
-	{0.00, "0d0+0", "0d0+0", I_WOOD, SK_MELEE, 0, 0, false, false, { 0, 0}, 0 }
+	{0.00, "0d0+0", "0d0+0", MAX_ITEMS, SK_MELEE, 0, 0, false, false, { 0, 0}, 0 }
 };
 
 weapon_type * oldweapontype[WP_MAX];
@@ -210,7 +202,7 @@ static void
 init_oldweapons(void)
 {
 	int w;
-	for (w=0;w!=WP_MAX && weapontable[w].item!=I_WOOD;++w) {
+	for (w=0;w!=WP_MAX && weapontable[w].item!=MAX_ITEMS;++w) {
 		const char * damage[2];
 		item_type * itype = olditemtype[weapontable[w].item];
 		int minskill = 1, wflags = WTF_NONE;
@@ -218,15 +210,6 @@ init_oldweapons(void)
 		weapon_mod * modifiers = NULL;
 		boolean (*attack)(const troop *, const struct weapon_type *, int *, int) = NULL;
 
-		switch (w) {
-		case WP_LANCE:
-			modifiers = wm_lance;
-			break;
-		case WP_SPEAR:
-			modifiers = wm_spear;
-			break;
-		}
-
 		assert(itype!=NULL || !"item not initialized");
 
 		if (weapontable[w].rear) wflags |= WTF_MISSILE;
diff --git a/src/common/kernel/alchemy.c b/src/common/kernel/alchemy.c
index bd455c3c8..375ddc63d 100644
--- a/src/common/kernel/alchemy.c
+++ b/src/common/kernel/alchemy.c
@@ -106,10 +106,10 @@ use_potion(unit * u, const item_type * itype, int amount, struct order *ord)
 
 		/* f�r die Aufforstung von Mallornw�ldern braucht man Mallorn */
 		if (fval(r, RF_MALLORN)) {
-			holz = use_pooled(u, oldresourcetype[R_MALLORN], 
+			holz = use_pooled(u, rt_find("mallorn"), 
 					GET_SLACK|GET_RESERVE|GET_POOLED_SLACK, 10*amount);
 		} else {
-			holz = use_pooled(u, oldresourcetype[R_WOOD], 
+			holz = use_pooled(u, rt_find("log"), 
 					GET_SLACK|GET_RESERVE|GET_POOLED_SLACK, 10*amount);
 		}
 	  if (r->land==0) holz=0;
diff --git a/src/common/kernel/building.c b/src/common/kernel/building.c
index 239f226d0..c7a75d25e 100644
--- a/src/common/kernel/building.c
+++ b/src/common/kernel/building.c
@@ -103,9 +103,14 @@ attrib_type at_building_action = {
   lc_write, lc_read
 };
 
-building_typelist *buildingtypes;
+typedef struct building_typelist {
+  struct building_typelist * next;
+  building_type * type;
+} building_typelist;
 
-const building_type *
+static building_typelist *buildingtypes;
+
+building_type *
 bt_find(const char* name)
 {
 	const struct building_typelist * btl = buildingtypes;
@@ -382,20 +387,6 @@ register_buildings(void)
 #endif
 }
 
-building_type *
-bt_make(const char * name, int flags, int capacity, int maxcapacity, int maxsize)
-{
-	building_type * btype = calloc(sizeof(building_type), 1);
-	btype->_name = name;
-	btype->flags = flags | BTF_DYNAMIC;
-	btype->capacity = capacity;
-	btype->maxcapacity = maxcapacity;
-	btype->maxsize = maxsize;
-
-	bt_register(btype);
-	return btype;
-}
-
 void *
 resolve_building(variant id) {
    return findbuilding(id.i);
diff --git a/src/common/kernel/building.h b/src/common/kernel/building.h
index 321e125ba..f16853264 100644
--- a/src/common/kernel/building.h
+++ b/src/common/kernel/building.h
@@ -60,16 +60,10 @@ typedef struct building_type {
 	struct attrib * attribs;
 } building_type;
 
-extern const building_type * bt_find(const char* name);
+extern building_type * bt_find(const char* name);
 extern void register_buildings(void);
 extern void bt_register(building_type * type);
 
-typedef struct building_typelist {
-	struct building_typelist * next;
-	const building_type * type;
-} building_typelist;
-
-extern struct building_typelist *buildingtypes;
 /* buildingt => building_type
  * Name => locale_string(name)
  * MaxGroesse => levels
@@ -129,8 +123,6 @@ void destroy_building(struct building * b);
 
 const struct building_type * findbuildingtype(const char * name, const struct locale * lang);
 
-extern struct building_type * bt_make(const char * name, int flags, int capacity, int maxcapacity, int maxsize);
-
 #include "build.h"
 #define NOBUILDING NULL
 
diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c
index 01009ec1b..04e3b8a72 100644
--- a/src/common/kernel/eressea.c
+++ b/src/common/kernel/eressea.c
@@ -3107,7 +3107,6 @@ attrib_init(void)
 	at_register(&at_moveblock);
 	at_register(&at_deathcount);
 	at_register(&at_chaoscount);
-	at_register(&at_woodcount);
 
 	/* neue UNIT-Attribute */
 	at_register(&at_siege);
diff --git a/src/common/kernel/give.c b/src/common/kernel/give.c
index 78ac4cbcd..e43f86766 100644
--- a/src/common/kernel/give.c
+++ b/src/common/kernel/give.c
@@ -155,11 +155,9 @@ give_men(int n, unit * u, unit * u2, struct order * ord)
     return;
   } else if (u == u2) {
     error = 10;
-#if RACE_ADJUSTMENTS
   } else if (!u2 && u->race == new_race[RC_SNOTLING]) {
     /* Snotlings k�nnen nicht an Bauern �bergeben werden. */
     error = 307;
-#endif
 #ifdef HEROES
   } else if (u2 && u2->number>0 && fval(u, UFL_HERO)!=fval(u2, UFL_HERO)) {
     error = 75;
diff --git a/src/common/kernel/item.c b/src/common/kernel/item.c
index d5a3ad8d9..4832fe0bd 100644
--- a/src/common/kernel/item.c
+++ b/src/common/kernel/item.c
@@ -641,149 +641,128 @@ use_tacticcrystal(region * r, unit * u, int amount, struct order * ord)
 	return;
 }
 
+typedef struct t_item {
+  const char *name[4];
+  /* [0]: Einzahl f�r eigene; [1]: Mehrzahl f�r eigene;
+  * [2]: Einzahl f�r Fremde; [3]: Mehrzahl f�r Fremde */
+  item_t typ;
+  skill_t skill;
+  int minskill;
+  int gewicht;
+  int preis;
+  unsigned int flags;
+  void (*benutze_funktion) (struct region *, struct unit *, int amount, struct order *);
+} t_item;
+
 static t_item itemdata[MAXITEMS] = {
 	/* name[4]; typ; sk; minskill; material[6]; gewicht; preis;
 	 * benutze_funktion; */
 	{			/* I_IRON */
 		{"Eisen", "Eisen", "Eisen", "Eisen"},
-		IS_RESOURCE, SK_MINING, 1, {0, 0, 0, 0, 0, 0}, 500, 0, FL_ITEM_NOTLOST, NULL
-	},
-	{			/* I_WOOD */
-		{"Holz", "Holz", "Holz", "Holz"},
-		IS_RESOURCE, SK_LUMBERJACK, 1, {0, 0, 0, 0, 0, 0}, 500, 0, FL_ITEM_NOTLOST, NULL
+		IS_RESOURCE, SK_MINING, 1, 500, 0, FL_ITEM_NOTLOST, NULL
 	},
 	{			/* I_STONE */
 		{"Stein", "Steine", "Stein", "Steine"},
-		IS_RESOURCE, SK_QUARRYING, 1, {0, 0, 0, 0, 0, 0}, 6000, 0, FL_ITEM_NOTLOST, NULL
+		IS_RESOURCE, SK_QUARRYING, 1, 6000, 0, FL_ITEM_NOTLOST, NULL
 	},
 	{			/* I_HORSE */
 		{"Pferd", "Pferde", "Pferd", "Pferde"},
-		IS_RESOURCE, SK_HORSE_TRAINING, 1, {0, 0, 0, 0, 0, 0}, 5000, 0, FL_ITEM_MOUNT | FL_ITEM_ANIMAL | FL_ITEM_NOTINBAG, NULL
-	},
-	{			/* I_WAGON */
-		{"Wagen", "Wagen", "Wagen", "Wagen"},
-		IS_PRODUCT, SK_CARTMAKER, 1, {0, 5, 0, 0, 0, 0}, 4000, 0, FL_ITEM_NOTINBAG, NULL
-	},
-	{			/* I_SPEAR */
-		{"Speer", "Speere", "Speer", "Speere"},
-		IS_PRODUCT, SK_WEAPONSMITH, 2, {0, 1, 0, 0, 0, 0}, 100, 0, 0, NULL
+		IS_RESOURCE, SK_HORSE_TRAINING, 1, 5000, 0, FL_ITEM_MOUNT | FL_ITEM_ANIMAL | FL_ITEM_NOTINBAG, NULL
 	},
 	{			/* I_AMULET_OF_HEALING */
 		{"Amulett der Heilung", "Amulette der Heilung", "Amulett", "Amulette"},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 0, 0, 0, NULL
+		IS_MAGIC, NOSKILL, 0, 0, 0, 0, NULL
 	},
 	{			/* I_AMULET_OF_TRUE_SEEING 22 */
 		{"Amulett des wahren Sehens", "Amulette des wahren Sehens", "Amulett",
 		"Amulette"},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 0, 0, 0, NULL
+		IS_MAGIC, NOSKILL, 0, 0, 0, 0, NULL
 	},
 	{			/* I_RING_OF_INVISIBILITY 24 */
 		{"Ring der Unsichtbarkeit", "Ringe der Unsichtbarkeit", "", ""},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 0, 0, 0, NULL
+		IS_MAGIC, NOSKILL, 0, 0, 0, 0, NULL
 	},
 	{			/* I_RING_OF_POWER 25 */
 		{"Ring der Macht", "Ringe der Macht", "", ""},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 0, 0, 0, NULL
+		IS_MAGIC, NOSKILL, 0, 0, 0, 0, NULL
 	},
 	{			/* I_DRAGONHEAD 33 */
 		{"Drachenkopf", "Drachenk�pfe", "Drachenkopf", "Drachenk�pfe"},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 500, 0, 0, NULL
+		IS_MAGIC, NOSKILL, 0, 500, 0, 0, NULL
 	},
 	{			/* I_CHASTITY_BELT 34 */
 		{"Amulett der Keuschheit", "Amulette der Keuschheit",
 			"Amulett", "Amulette"},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 0, 0, 0, NULL
-	},
-	{			/* I_LAENSWORD 38 */
-		{"Laenschwert", "Laenschwerter", "Laenschwert", "Laenschwerter"},
-		IS_PRODUCT, SK_WEAPONSMITH, 8, {0, 0, 0, 0, 1, 0}, 100, 0, 0, NULL
+		IS_MAGIC, NOSKILL, 0, 0, 0, 0, NULL
 	},
 	{			/* I_LAEN 41 */
 		{"Laen", "Laen", "Laen", "Laen"},
-		IS_RESOURCE, SK_MINING, 7, {0, 0, 0, 0, 0, 0}, 200, 0, 0, NULL
-	},
-	{			/* I_LANCE 44 */
-		{"Lanze", "Lanzen", "Lanze", "Lanzen"},
-		IS_PRODUCT, SK_WEAPONSMITH, 2, {0, 2, 0, 0, 0, 0}, 200, 0, 0, NULL
-	},
-	{			/* I_MALLORN 45 */
-		{"Mallorn", "Mallorn", "Mallorn", "Mallorn"},
-		IS_RESOURCE, SK_LUMBERJACK, 2, {0, 0, 0, 0, 0, 0}, 500, 0, 0, NULL
+		IS_RESOURCE, SK_MINING, 7, 200, 0, 0, NULL
 	},
 	{			/* I_DRACHENBLUT 59 */
 		{"Drachenblut", "Drachenblut", "Drachenblut", "Drachenblut"},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 100, 0, 0, NULL
+		IS_MAGIC, NOSKILL, 0, 100, 0, 0, NULL
 	},
 	{			/* I_FEENSTIEFEL 60 */
 		{"Feenstiefel", "Feenstiefel", "Feenstiefel", "Feenstiefel"},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 0, 0, 0, NULL
+		IS_MAGIC, NOSKILL, 0, 0, 0, 0, NULL
 	},
 	{			/* I_BIRTHDAYAMULET 69 */
 		{"Katzenamulett", "Katzenamulette", "Amulett", "Amulette"},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 100, 0, 0, &use_birthdayamulet
+		IS_MAGIC, NOSKILL, 0, 100, 0, 0, &use_birthdayamulet
 	},
 	{			/* I_PEGASUS 60 */
 		{"Pegasus", "Pegasi", "Pegasus", "Pegasi" },
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 5000, 0, FL_ITEM_ANIMAL | FL_ITEM_NOTINBAG | FL_ITEM_NOTLOST, NULL
+		IS_MAGIC, NOSKILL, 0, 5000, 0, FL_ITEM_ANIMAL | FL_ITEM_NOTINBAG | FL_ITEM_NOTLOST, NULL
 	},
 	{			/* I_UNICORN 61 */
 		{"Elfenpferd", "Elfenpferde", "Elfenpferd", "Elfenpferde"},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 5000, 0, FL_ITEM_ANIMAL | FL_ITEM_NOTINBAG | FL_ITEM_NOTLOST, NULL
+		IS_MAGIC, NOSKILL, 0, 5000, 0, FL_ITEM_ANIMAL | FL_ITEM_NOTINBAG | FL_ITEM_NOTLOST, NULL
 	},
 	{			/* I_DOLPHIN 62 */
 		{"Delphin", "Delphine", "Delphin", "Delphine"},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 5000, 0, FL_ITEM_ANIMAL | FL_ITEM_NOTINBAG | FL_ITEM_NOTLOST, NULL
+		IS_MAGIC, NOSKILL, 0, 5000, 0, FL_ITEM_ANIMAL | FL_ITEM_NOTINBAG | FL_ITEM_NOTLOST, NULL
 	},
 	{			/* I_RING_OF_NIMBLEFINGER 64 */
 		{"Ring der flinken Finger", "Ringe der flinken Finger", "", ""},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 0, 0, 0, NULL
+		IS_MAGIC, NOSKILL, 0, 0, 0, 0, NULL
 	},
 	{			/* I_TROLLBELT 65 */
 		{"G�rtel der Trollst�rke", "G�rtel der Trollst�rke", "", ""},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 0, 0, 0, NULL
+		IS_MAGIC, NOSKILL, 0, 0, 0, 0, NULL
 	},
 	{			/* I_PRESSCARD 67 */
 		{"Akkredition des Xontormia-Expre�", "Akkreditionen des Xontormia-Expre�",
 		 "Akkredition des Xontormia-Expre�", "Akkreditionen des Xontormia-Expre�"},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 0, 0, FL_ITEM_CURSED, NULL
+		IS_MAGIC, NOSKILL, 0, 0, 0, FL_ITEM_CURSED, NULL
 	},
 	{			/* I_AURAKULUM 69 */
 		{"Aurafocus", "Aurafocuse", "Amulett", "Amulette"},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 100, 0, 0, NULL
+		IS_MAGIC, NOSKILL, 0, 100, 0, 0, NULL
 	},
 	{			/* I_SEASERPENTHEAD 70 */
 		{"Seeschlangenkopf", "Seeschlangenk�pfe",
 			"Seeschlangenkopf", "Seeschlangenk�pfe"},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 500, 0, 0, NULL
+		IS_MAGIC, NOSKILL, 0, 500, 0, 0, NULL
 	},
   {			/* I_SPHERE_OF_INVISIBILITY */
     {"Sph�re der Unsichtbarkeit", "Sph�ren der Unsichtbarkeit", "", ""},
-      IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 100, 0, 0, NULL
+      IS_MAGIC, NOSKILL, 0, 100, 0, 0, NULL
   },
   { /* I_BAG_OF_HOLDING */
     {"Zauberbeutel", "Zauberbeutel", "Zauberbeutel", "Zauberbeutel"},
-      IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 100, 0, FL_ITEM_NOTINBAG|FL_ITEM_NOTLOST, NULL
+      IS_MAGIC, NOSKILL, 0, 100, 0, FL_ITEM_NOTINBAG|FL_ITEM_NOTLOST, NULL
   },
   { /* I_SACK_OF_CONSERVATION */
     {"Magischer Kr�uterbeutel", "Magische Kr�uterbeutel", "", ""},
-      IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 100, 0, 0, NULL
+      IS_MAGIC, NOSKILL, 0, 100, 0, 0, NULL
   },
 	{			/* I_TACTICCRYSTAL 71 */
-		{"Traumauge", "Traumaugen",
-			"", ""},
-		IS_MAGIC, 0, 0, {0, 0, 0, 0, 0, 0}, 100, 0, 0, &use_tacticcrystal
+		{"Traumauge", "Traumaugen", "", ""},
+		IS_MAGIC, NOSKILL, 0, 100, 0, 0, &use_tacticcrystal
 	},
 };
 
-const item_t matresource[] = {
-	I_IRON,
-	I_WOOD,
-	I_STONE,
-	-1,
-	I_LAEN,
-	I_MALLORN
-};
-
 #include "movement.h"
 
 static int
@@ -794,27 +773,11 @@ mod_elves_only(const unit * u, const region * r, skill_t sk, int value)
 	return -118;
 }
 
-typedef int material_t;
-enum {	/* Vorsicht! Reihenfolge der ersten 3 mu� wie I_IRON ... sein! */
-	M_EISEN,
-	M_HOLZ,
-	M_STEIN,
-	M_SILBER,
-	M_EOG,
-	M_MALLORN,
-	M_MAX_MAT,
-	NOMATERIAL = (material_t) - 1
-};
-
 static int
-limit_oldtypes(const region * r, const resource_type * rtype)
+limit_oldresource(const region * r, const resource_type * rtype)
 		/* TODO: split into seperate functions. really much nicer. */
 {
-	if (rtype==oldresourcetype[R_WOOD]) {
-		return rtrees(r,2) + rtrees(r,1);
-	} else if (rtype==oldresourcetype[R_MALLORN]) {
-		return rtrees(r,2) + rtrees(r,1);
-	} else if (rtype==oldresourcetype[R_HORSE]) {
+	if (rtype==oldresourcetype[R_HORSE]) {
 		return rhorses(r);
 	} else {
 		assert(!"das kann man nicht produzieren!");
@@ -824,35 +787,15 @@ limit_oldtypes(const region * r, const resource_type * rtype)
 
 
 static void
-use_oldresource(region * r, const resource_type * rtype, int norders)
+produce_oldresource(region * r, const resource_type * rtype, int norders)
 		/* TODO: split into seperate functions. really much nicer. */
 {
 	assert(norders>0);
-	if (rtype==oldresourcetype[R_WOOD] || rtype==oldresourcetype[R_MALLORN]) {
-		int avail_grownup = rtrees(r,2);
-		int avail_young   = rtrees(r,1);
-		int wcount;
-
-		assert(norders <= avail_grownup + avail_young);
-
-		if(norders <= avail_grownup) {
-			rsettrees(r, 2, avail_grownup-norders);
-			wcount = norders;
-		} else {
-			rsettrees(r, 2, 0);
-			rsettrees(r, 1, avail_young-(norders-avail_grownup));
-			wcount = norders * 3;
-		}
-		if(rtype==oldresourcetype[R_MALLORN]) {
-			woodcounts(r, wcount);
-		} else {
-			woodcounts(r, wcount*2);
-		}
-	} else if (rtype==oldresourcetype[R_HORSE]) {
+	if (rtype==oldresourcetype[R_HORSE]) {
 		int avail = rhorses(r);
 		assert(norders <= avail);
 		rsethorses(r, avail-norders);
-	} else if (rtype!=oldresourcetype[R_STONE]) {
+	} else {
 		assert(!"unknown resource");
 	}
 }
@@ -961,9 +904,6 @@ init_olditems(void)
       itype->capacity = HORSECAPACITY;
       itype->give = give_horses;
       break;
-    case I_WAGON:
-      itype->capacity = WAGONCAPACITY;
-      break;
     case I_BAG_OF_HOLDING:
       itype->capacity = BAGCAPACITY;
       break;
@@ -985,8 +925,11 @@ init_olditems(void)
       a = a_add(&rtype->attribs, a_new(&at_resourcelimit));
       {
         resource_limit * rdata = (resource_limit*)a->data.v;
-        rdata->limit = limit_oldtypes;
-        rdata->use = use_oldresource;
+        if (i==I_HORSE) {
+          rdata->limit = limit_oldresource;
+          rdata->produce = produce_oldresource;
+        }
+        if (i==I_LAEN || i==I_IRON) rdata->guard |= GUARD_MINING;
       }
       break;
     }
@@ -998,35 +941,21 @@ init_olditems(void)
   }
 
   for (i=0; i!=MAXITEMS; ++i) {
-    construction * con = calloc(sizeof(construction), 1);
-    item_type * itype = olditemtype[i];
-    int m, n;
+    if (itemdata[i].skill!=NOSKILL) {
+      construction * con = calloc(sizeof(construction), 1);
+      item_type * itype = olditemtype[i];
 
-    con->minskill = itemdata[i].minskill;
-    if (i==I_LAEN && SkillCap(SK_QUARRYING)) {
-      /* at least 4 levels on which you can mine laen */
-      con->minskill = SkillCap(SK_QUARRYING)-3;
-    }
-    con->skill = itemdata[i].skill;
-    con->maxsize = -1;
-    con->reqsize = 1;
-    con->improvement = NULL;
-    for (m=0, n=0;m!=M_MAX_MAT;++m)
-      if (itemdata[i].material[m]>0) ++n;
-    if (n>0) {
-      con->materials = calloc(sizeof(requirement), n+1);
-      for (m=0, n=0;m!=M_MAX_MAT;++m) {
-        if (itemdata[i].material[m]>0) {
-          assert(oldresourcetype[matresource[m]]);
-          con->materials[n].rtype = oldresourcetype[matresource[m]];
-          con->materials[n].number = itemdata[i].material[m];
-          con->materials[n].recycle = 0.0;
-          ++n;
-        }
+      con->minskill = itemdata[i].minskill;
+      if (i==I_LAEN && SkillCap(SK_QUARRYING)) {
+        /* at least 4 levels on which you can mine laen */
+        con->minskill = SkillCap(SK_QUARRYING)-3;
       }
+      con->skill = itemdata[i].skill;
+      con->maxsize = -1;
+      con->reqsize = 1;
+      con->improvement = NULL;
+      itype->construction = con;
     }
-
-    itype->construction = con;
   }
 }
 
@@ -1303,18 +1232,11 @@ item_score(item_t i)
 {
   switch (i) {
     case I_IRON:
-    case I_WOOD:
     case I_STONE:
     case I_HORSE:
       return 10;
-    case I_MALLORN:
-      return 30;
     case I_LAEN:
       return 100;
-    case I_WAGON:
-      return 60;
-    case I_LAENSWORD:
-      return 400;
     case I_AMULET_OF_HEALING:
     case I_AMULET_OF_TRUE_SEEING:
     case I_RING_OF_INVISIBILITY:
@@ -1541,9 +1463,6 @@ register_resources(void)
   register_function((pf_generic)res_changehp, "changehp");
   register_function((pf_generic)res_changeaura, "changeaura");
 
-  register_function((pf_generic)limit_oldtypes, "limit_oldtypes");
-
-  register_function((pf_generic)use_oldresource, "useoldresource");
   register_function((pf_generic)use_olditem, "useolditem");
   register_function((pf_generic)use_potion, "usepotion");
   register_function((pf_generic)use_tacticcrystal, "usetacticcrystal");
diff --git a/src/common/kernel/item.h b/src/common/kernel/item.h
index 7a9334d39..b67b792b5 100644
--- a/src/common/kernel/item.h
+++ b/src/common/kernel/item.h
@@ -76,13 +76,25 @@ extern const char* resourcename(const resource_type * rtype, int flags);
 extern const resource_type * findresourcetype(const char * name, const struct locale * lang);
 
 /* resource-limits for regions */
+#define RMF_SKILL         0x01 /* int, bonus on resource production skill */
+#define RMF_SAVEMATERIAL  0x02 /* float, multiplier on resource usage */
+#define RMF_SAVERESOURCE  0x03 /* int, bonus on resource production skill */
+typedef struct resource_mod {
+  variant value;
+  const struct building_type * btype;
+  const struct race * race;
+  unsigned int flags;
+} resource_mod;
+
 extern struct attrib_type at_resourcelimit;
 typedef int (*rlimit_limit)(const struct region * r, const struct resource_type * rtype);
-typedef void (*rlimit_use)(struct region * r, const struct resource_type * rtype, int n);
+typedef void (*rlimit_produce)(struct region * r, const struct resource_type * rtype, int n);
 typedef struct resource_limit {
 	rlimit_limit limit;
-	rlimit_use use;
+	rlimit_produce produce;
+  unsigned int guard; /* how to guard against theft */
 	int value;
+  resource_mod * modifiers;
 } resource_limit;
 
 
@@ -93,6 +105,7 @@ typedef struct resource_limit {
 #define ITF_NOTLOST          0x0020 /* special object (quests), cannot be lost through death etc. */
 #define ITF_BIG              0x0040 /* big item, e.g. does not fit in a bag of holding */
 #define ITF_ANIMAL           0x0080 /* an animal */
+#define ITF_VEHICLE          0x0100 /* a vehicle, drawn by two animals */
 
 /* error codes for item_type::use */
 #define ECUSTOM   -1;
@@ -240,27 +253,10 @@ extern resource_type * r_permaura;
 extern resource_type * r_unit;
 extern resource_type * r_hp;
 
-typedef struct t_item {
-	const char *name[4];
-	/* [0]: Einzahl f�r eigene; [1]: Mehrzahl f�r eigene;
-	 * [2]: Einzahl f�r Fremde; [3]: Mehrzahl f�r Fremde */
-	item_t typ;
-	skill_t skill;
-	int minskill;
-	int material[6];
-	int gewicht;
-	int preis;
-	unsigned int flags;
-	void (*benutze_funktion) (struct region *, struct unit *, int amount, struct order *);
-} t_item;
-
 enum {
 	I_IRON,						/* 0 */
-	I_WOOD,
 	I_STONE,
 	I_HORSE,
-	I_WAGON,
-	I_SPEAR,
 	/* alte Artefakte */
 	I_AMULET_OF_HEALING,
 	I_AMULET_OF_TRUE_SEEING,
@@ -268,10 +264,7 @@ enum {
 	I_RING_OF_POWER,
 	I_DRAGONHEAD,
 	I_CHASTITY_BELT, /* bleibt */
-	I_LAENSWORD,
 	I_LAEN,
-	I_LANCE,
-	I_MALLORN,
 	I_DRACHENBLUT,
 	I_FEENSTIEFEL,
 	I_BIRTHDAYAMULET,
@@ -293,11 +286,8 @@ enum {
 enum {
 	/* ITEMS: */
 	R_IRON,
-	R_WOOD,
 	R_STONE,
 	R_HORSE,
-	R_WAGON,
-	R_SPEAR,
   /**/
 	R_AMULET_OF_HEALING,
 	R_AMULET_OF_TRUE_SEEING,
@@ -305,10 +295,7 @@ enum {
 	R_RING_OF_POWER,
 	R_DRAGONHEAD,
 	R_CHASTITY_BELT,
-	R_EOGSWORD,
 	R_EOG,
-	R_LANCE,
-	R_MALLORN,
 	R_DRACHENBLUT,
 	R_FEENSTIEFEL,
 	R_BIRTHDAYAMULET,
diff --git a/src/common/kernel/movement.c b/src/common/kernel/movement.c
index bb880ce0d..0d2473e81 100644
--- a/src/common/kernel/movement.c
+++ b/src/common/kernel/movement.c
@@ -208,18 +208,7 @@ entrance_allowed(const struct unit * u, const struct region * r)
 int
 personcapacity(const unit *u)
 {
-#ifdef RACE_CAPACITY
 	int cap = u->race->weight+u->race->capacity;
-#else
-	int cap = u->race->weight+540;
-
-	if (u->race == new_race[RC_TROLL])
-		cap += 540;
-#if RACE_ADJUSTMENTS
-	else if (u->race == new_race[RC_GOBLIN])
-		cap -= 100;
-#endif
-#endif
 	
 	if (fspecial(u->faction, FS_QUICK))
 		cap -= 200;
@@ -237,75 +226,101 @@ eff_weight(const unit *u)
 	return weight(u);
 }
 
+static void
+get_transporters(const item * itm, int * p_animals, int *p_acap, int * p_vehicles, int * p_vcap)
+{
+  int vehicles = 0, vcap = 0;
+  int animals = 0, acap = 0;
+
+  for (;itm!=NULL;itm=itm->next) {
+    const item_type * itype = itm->type;
+    if (itype->capacity>0) {
+      if (itype->flags & ITF_ANIMAL) {
+        ++animals;
+        if (acap==0) acap = itype->capacity;
+        assert(acap==itype->capacity || !"animals with different capacity not supported");
+      }
+      if (itype->flags & ITF_VEHICLE) {
+        ++vehicles;
+        if (vcap==0) vcap = itype->capacity;
+        assert(vcap==itype->capacity || !"vehicles with different capacity not supported");
+      }
+    }
+  }
+  *p_vehicles = vehicles;
+  *p_animals = animals;
+  *p_vcap = vcap;
+  *p_acap = acap;
+}
+
 static int
 ridingcapacity(unit * u)
 {
-	int n;
-	int wagen, pferde;
+	int vehicles = 0, vcap = 0;
+  int animals = 0, acap = 0;
 
-	n = 0;
+  get_transporters(u->items, &animals, &acap, &vehicles, &vcap);
 
-	/* Man tr�gt sein eigenes Gewicht plus seine Kapazit�t! Die Menschen
-	 * tragen nichts (siehe walkingcapacity). Ein Wagen z�hlt nur, wenn er
-	 * von zwei Pferden gezogen wird */
+  /* Man tr�gt sein eigenes Gewicht plus seine Kapazit�t! Die Menschen
+   * tragen nichts (siehe walkingcapacity). Ein Wagen z�hlt nur, wenn er
+   * von zwei Pferden gezogen wird */
 
-  pferde = get_item(u, I_HORSE) + get_item(u, I_UNICORN);
-  pferde = min(pferde, effskill(u, SK_RIDING) * u->number * 2);
-	if (fval(u->race, RCF_HORSE)) pferde += u->number;
+  animals = min(animals, effskill(u, SK_RIDING) * u->number * 2);
+	if (fval(u->race, RCF_HORSE)) animals += u->number;
 
 	/* maximal diese Pferde k�nnen zum Ziehen benutzt werden */
-	wagen = min(pferde / HORSESNEEDED, get_item(u, I_WAGON));
+	vehicles = min(animals / HORSESNEEDED, vehicles);
 
-	n = wagen * WAGONCAPACITY + pferde * HORSECAPACITY;
-	return n;
+	return vehicles * vcap + animals * acap;
 }
 
 int
 walkingcapacity(const struct unit * u)
 {
-	int n, tmp, personen, pferde_fuer_wagen;
-	int wagen, wagen_ohne_pferde, wagen_mit_pferden, wagen_mit_trollen;
-	/* Das Gewicht, welches die Pferde tragen, plus das Gewicht, welches
+	int n, tmp, people, pferde_fuer_wagen;
+	int wagen_ohne_pferde, wagen_mit_pferden, wagen_mit_trollen;
+  int vehicles = 0, vcap = 0;
+  int animals = 0, acap = 0;
+
+  get_transporters(u->items, &animals, &acap, &vehicles, &vcap);
+
+  /* Das Gewicht, welches die Pferde tragen, plus das Gewicht, welches
 	 * die Leute tragen */
 
-	int pferde = get_item(u, I_HORSE) + get_item(u, I_UNICORN);
+  pferde_fuer_wagen = min(animals, effskill(u, SK_RIDING) * u->number * 4);
 	if (fval(u->race, RCF_HORSE)) {
-		pferde += u->number;
-		personen = 0;
+		animals += u->number;
+		people = 0;
 	} else {
-		personen = u->number;
+		people = u->number;
 	}
-	wagen = get_item(u, I_WAGON);
-
-	pferde_fuer_wagen = min(pferde, effskill(u, SK_RIDING) * u->number * 4);
 
 	/* maximal diese Pferde k�nnen zum Ziehen benutzt werden */
+	wagen_mit_pferden = min(vehicles, pferde_fuer_wagen / HORSESNEEDED);
 
-	wagen_mit_pferden = min(wagen, pferde_fuer_wagen / HORSESNEEDED);
-
-	n = wagen_mit_pferden * WAGONCAPACITY;
+	n = wagen_mit_pferden * vcap;
 
 	if (u->race == new_race[RC_TROLL]) {
 		/* 4 Trolle ziehen einen Wagen. */
 		/* Unbesetzte Wagen feststellen */
-		wagen_ohne_pferde = wagen - wagen_mit_pferden;
+		wagen_ohne_pferde = vehicles - wagen_mit_pferden;
 
 		/* Genug Trolle, um die Restwagen zu ziehen? */
 		wagen_mit_trollen = min(u->number / 4, wagen_ohne_pferde);
 
 		/* Wagenkapazit�t hinzuz�hlen */
-		n += wagen_mit_trollen * WAGONCAPACITY;
+		n += wagen_mit_trollen * vcap;
 		wagen_ohne_pferde -= wagen_mit_trollen;
 	}
 
-	n += pferde * HORSECAPACITY;
-	n += personen * personcapacity(u);
+	n += animals * acap;
+	n += people * personcapacity(u);
 	/* Goliathwasser */
   tmp = get_effect(u, oldpotiontype[P_STRONG]);
-	n += min(personen, tmp) * (HORSECAPACITY - personcapacity(u));
+	n += min(people, tmp) * (acap - personcapacity(u));
   /* change_effect wird in ageing gemacht */
   tmp = get_item(u, I_TROLLBELT);
-	n += min(personen, tmp) * (STRENGTHMULTIPLIER-1) * personcapacity(u);
+	n += min(people, tmp) * (STRENGTHMULTIPLIER-1) * personcapacity(u);
 
 	return n;
 }
@@ -320,16 +335,16 @@ enum {
 static int
 canwalk(unit * u)
 {
-	int wagen, maxwagen;
-	int pferde, maxpferde;
+	int maxwagen, maxpferde;
+  int vehicles = 0, vcap = 0;
+  int animals = 0, acap = 0;
 
-	/* workaround: monsters are too stupid to drop items, therefore they have
+  /* workaround: monsters are too stupid to drop items, therefore they have
 	 * infinite carrying capacity */
 
-	if (u->faction->no == 0) return E_CANWALK_OK;
+	if (u->faction->no == MONSTER_FACTION) return E_CANWALK_OK;
 
-	wagen = get_item(u, I_WAGON);
-	pferde = get_item(u, I_HORSE) + get_item(u, I_UNICORN);
+  get_transporters(u->items, &animals, &acap, &vehicles, &vcap);
 
 	maxwagen = effskill(u, SK_RIDING) * u->number * 2;
 	if (u->race == new_race[RC_TROLL]) {
@@ -337,7 +352,7 @@ canwalk(unit * u)
 	}
 	maxpferde = effskill(u, SK_RIDING) * u->number * 4 + u->number;
 
-	if (pferde > maxpferde)
+	if (animals > maxpferde)
 		return E_CANWALK_TOOMANYHORSES;
 
 	if (walkingcapacity(u) - eff_weight(u) >= 0)
@@ -348,7 +363,7 @@ canwalk(unit * u)
 	 * die Einheit nicht zum Ziehen benutzt, also nicht mehr Wagen gezogen
 	 * als erlaubt. */
 
-	if (wagen > maxwagen)
+	if (vehicles > maxwagen)
 		return E_CANWALK_TOOMANYCARTS;
 	/* Es mu� nicht zwingend an den Wagen liegen, aber egal... (man
 	 * k�nnte z.B. auch 8 Eisen abladen, damit ein weiterer Wagen als
diff --git a/src/common/kernel/region.c b/src/common/kernel/region.c
index 68141849b..2f548a137 100644
--- a/src/common/kernel/region.c
+++ b/src/common/kernel/region.c
@@ -136,13 +136,6 @@ chaoscount(const region * r) {
 	return a->data.i;
 }
 
-int
-woodcount(const region * r) {
-	attrib * a = a_find(r->attribs, &at_woodcount);
-	if (!a) return 0;
-	return a->data.i;
-}
-
 void
 deathcounts (region * r, int fallen) {
 	attrib * a;
@@ -170,19 +163,6 @@ chaoscounts(region * r, int fallen) {
 	if (a->data.i<=0) a_remove(&r->attribs, a);
 }
 
-void
-woodcounts(region * r, int fallen) {
-	attrib * a;
-
-	if (fallen==0) return;
-
-	a = a_find(r->attribs, &at_woodcount);
-	if (!a) a = a_add(&r->attribs, a_new(&at_woodcount));
-	a->data.i += fallen;
-
-	if (a->data.i<=0) a_remove(&r->attribs, a);
-}
-
 /********************/
 /*   at_direction   */
 /********************/
@@ -508,7 +488,7 @@ attrib_type at_woodcount = {
 	DEFAULT_INIT,
 	DEFAULT_FINALIZE,
 	DEFAULT_AGE,
-	a_writeint,
+	NO_WRITE,
 	a_readint,
 	ATF_UNIQUE
 };
diff --git a/src/common/kernel/region.h b/src/common/kernel/region.h
index deb2ab03b..c31efd978 100644
--- a/src/common/kernel/region.h
+++ b/src/common/kernel/region.h
@@ -164,11 +164,9 @@ extern struct attrib *create_special_direction(struct region *r, struct region *
                                                int duration, const char *desc, 
                                                const char *keyword);
 
-int woodcount(const struct region * r);
 int deathcount(const struct region * r);
 int chaoscount(const struct region * r);
 
-void woodcounts(struct region * r, int delta);
 void deathcounts(struct region * r, int delta);
 void chaoscounts(struct region * r, int delta);
 
diff --git a/src/common/kernel/xmlreader.c b/src/common/kernel/xmlreader.c
index 1ff240893..0944de0d9 100644
--- a/src/common/kernel/xmlreader.c
+++ b/src/common/kernel/xmlreader.c
@@ -243,36 +243,41 @@ parse_buildings(xmlDocPtr doc)
     for (i=0;i!=nodes->nodeNr;++i) {
       xmlNodePtr node = nodes->nodeTab[i];
       xmlChar * property;
-      building_type * bt = calloc(sizeof(building_type), 1);
+      building_type * btype;
       xmlXPathObjectPtr result;
       int k;
 
       property = xmlGetProp(node, BAD_CAST "name");
       assert(property!=NULL);
-      bt->_name = strdup((const char *)property);
+      btype = bt_find((const char*)property);
+      if (btype==NULL) {
+        btype = calloc(sizeof(building_type), 1);
+        btype->_name = strdup((const char *)property);
+        bt_register(btype);
+      }
       xmlFree(property);
 
-      bt->capacity = xml_ivalue(node, "capacity", -1);
-      bt->maxcapacity = xml_ivalue(node, "maxcapacity", -1);
-      bt->maxsize = xml_ivalue(node, "maxsize", -1);
+      btype->capacity = xml_ivalue(node, "capacity", -1);
+      btype->maxcapacity = xml_ivalue(node, "maxcapacity", -1);
+      btype->maxsize = xml_ivalue(node, "maxsize", -1);
 
-      bt->magres = xml_ivalue(node, "magres", 0);
-      bt->magresbonus = xml_ivalue(node, "magresbonus", 0);
-      bt->fumblebonus = xml_ivalue(node, "fumblebonus", 0);
-      bt->auraregen = xml_fvalue(node, "auraregen", 1.0);
+      btype->magres = xml_ivalue(node, "magres", 0);
+      btype->magresbonus = xml_ivalue(node, "magresbonus", 0);
+      btype->fumblebonus = xml_ivalue(node, "fumblebonus", 0);
+      btype->auraregen = xml_fvalue(node, "auraregen", 1.0);
 
-      if (xml_bvalue(node, "nodestroy", false)) bt->flags |= BTF_INDESTRUCTIBLE;
-      if (xml_bvalue(node, "oneperturn", false)) bt->flags |= BTF_ONEPERTURN;
-      if (xml_bvalue(node, "nobuild", false)) bt->flags |= BTF_NOBUILD;
-      if (xml_bvalue(node, "unique", false)) bt->flags |= BTF_UNIQUE;
-      if (xml_bvalue(node, "decay", false)) bt->flags |= BTF_DECAY;
-      if (xml_bvalue(node, "magic", false)) bt->flags |= BTF_MAGIC;
-      if (xml_bvalue(node, "protection", false)) bt->flags |= BTF_PROTECTION;
+      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, "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, "protection", false)) btype->flags |= BTF_PROTECTION;
 
       /* reading eressea/buildings/building/construction */
       xpath->node = node;
       result = xmlXPathEvalExpression(BAD_CAST "construction", xpath);
-      xml_readconstruction(xpath, result->nodesetval->nodeTab, result->nodesetval->nodeNr, &bt->construction);
+      xml_readconstruction(xpath, result->nodesetval->nodeTab, result->nodesetval->nodeNr, &btype->construction);
       xmlXPathFreeObject(result);
 
       if (gamecode_enabled) {
@@ -286,18 +291,18 @@ parse_buildings(xmlDocPtr doc)
 
           if (fun==NULL) {
             log_error(("unknown function name '%s' for building %s\n",
-              (const char*)property, bt->_name));
+              (const char*)property, btype->_name));
             xmlFree(property);
             continue;
           }
           assert(property!=NULL);
           if (strcmp((const char*)property, "name")==0) {
-            bt->name = (const char * (*)(int size))fun;
+            btype->name = (const char * (*)(int size))fun;
           } else if (strcmp((const char*)property, "init")==0) {
-            bt->init = (void (*)(struct building_type*))fun;
+            btype->init = (void (*)(struct building_type*))fun;
           } else {
             log_error(("unknown function type '%s' for building %s\n",
-              (const char*)property, bt->_name));
+              (const char*)property, btype->_name));
           }
           xmlFree(property);
         }
@@ -310,10 +315,10 @@ parse_buildings(xmlDocPtr doc)
         xmlNodePtr node = result->nodesetval->nodeTab[k];
         maintenance * mt;
 
-        if (bt->maintenance==NULL) {
-          bt->maintenance = calloc(sizeof(struct maintenance), result->nodesetval->nodeNr+1);
+        if (btype->maintenance==NULL) {
+          btype->maintenance = calloc(sizeof(struct maintenance), result->nodesetval->nodeNr+1);
         }
-        mt = bt->maintenance + k;
+        mt = btype->maintenance + k;
         mt->number = xml_ivalue(node, "amount", 0);
 
         property = xmlGetProp(node, BAD_CAST "type");
@@ -328,8 +333,8 @@ parse_buildings(xmlDocPtr doc)
       }
       xmlXPathFreeObject(result);
 
-      /* finally, register the new building type */
-      bt_register(bt);
+      /* finally, initialize the new building type */
+      if (btype->init) btype->init(btype);
     }
   }
   xmlXPathFreeObject(buildings);
@@ -652,7 +657,7 @@ xml_readweapon(xmlXPathContextPtr xpath, item_type * itype)
   xpath->node = node;
   result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
   assert(wtype->modifiers==NULL);
-  wtype->modifiers = calloc(sizeof(weapon_mod), result->nodesetval->nodeNr+1);
+  wtype->modifiers = calloc(result->nodesetval->nodeNr+1, sizeof(weapon_mod));
   for (k=0;k!=result->nodesetval->nodeNr;++k) {
     xmlNodePtr node = result->nodesetval->nodeTab[k];
     xmlXPathObjectPtr races;
@@ -740,6 +745,7 @@ xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
   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 = new_itemtype(rtype, flags, weight, capacity);
 #ifdef SCORE_MODULE
   itype->score = xml_ivalue(node, "score", 0);
@@ -917,41 +923,120 @@ parse_resources(xmlDocPtr doc)
       xmlXPathFreeObject(result);
     }
 
+    /* reading eressea/resources/resource/resourcelimit */
+    xpath->node = node;
+    result = xmlXPathEvalExpression(BAD_CAST "resourcelimit", xpath);
+    assert(result->nodesetval->nodeNr<=1);
+    if (result->nodesetval->nodeNr!=0) {
+      resource_limit * rdata;
+      attrib * a = a_find(rtype->attribs, &at_resourcelimit);
+      xmlNodePtr limit = result->nodesetval->nodeTab[0];
+
+      if (a==NULL) a = a_add(&rtype->attribs, a_new(&at_resourcelimit));
+      rdata = (resource_limit*)a->data.v;
+      rtype->flags |= RTF_LIMITED;
+      xpath->node = limit;
+      xmlXPathFreeObject(result);
+
+      result = xmlXPathEvalExpression(BAD_CAST "modifier", xpath);
+      if (result->nodesetval!=NULL) {
+        rdata->modifiers = calloc(result->nodesetval->nodeNr+1, sizeof(resource_mod));
+        for (k=0;k!=result->nodesetval->nodeNr;++k) {
+          xmlNodePtr node = result->nodesetval->nodeTab[k];
+          building_type * btype = NULL;
+          const race * rc = NULL;
+
+          property = xmlGetProp(node, BAD_CAST "race");
+          if (property!=NULL) {
+            rc = rc_find((const char*)property);
+            if (rc==NULL) rc = rc_add(rc_new((const char*)property));
+            xmlFree(property);
+          }
+          rdata->modifiers[k].race = rc;
+
+          property = xmlGetProp(node, BAD_CAST "building");
+          if (property!=NULL) {
+            btype = bt_find((const char*)property);
+            if (btype==NULL) {
+              btype = calloc(sizeof(building_type), 1);
+              btype->_name = strdup((const char *)property);
+              bt_register(btype);
+            }
+            xmlFree(property);
+          }
+          rdata->modifiers[k].btype = btype;
+
+          property = xmlGetProp(node, BAD_CAST "type");
+          assert(property!=NULL);
+          if (strcmp((const char *)property, "skill")) {
+            rdata->modifiers[k].value.i = xml_ivalue(node, "value", 0);
+            rdata->modifiers[k].flags |= RMF_SKILL;
+          } else if (strcmp((const char *)property, "material")) {
+            rdata->modifiers[k].value.f = (float)xml_fvalue(node, "value", 0);
+            rdata->modifiers[k].flags |= RMF_SAVEMATERIAL;
+          } else if (strcmp((const char *)property, "resource")) {
+            rdata->modifiers[k].value.f = (float)xml_fvalue(node, "value", 0);
+            rdata->modifiers[k].flags |= RMF_SAVERESOURCE;
+          } else {
+            log_error(("unknown type '%s' for resourcelimit-modifier '%s'\n",
+              (const char*)property, rtype->_name[0]));
+          }
+          xmlFree(property);
+        }
+      }
+      xmlXPathFreeObject(result);
+
+      result = xmlXPathEvalExpression(BAD_CAST "guard", xpath);
+      if (result->nodesetval!=NULL) for (k=0;k!=result->nodesetval->nodeNr;++k) {
+        xmlNodePtr node = result->nodesetval->nodeTab[k];
+        xmlChar * flag = xmlGetProp(node, BAD_CAST "flag");
+        
+        if (flag!=NULL) {
+          if (strcmp((char*)flag, "logging")==0) {
+            rdata->guard |= GUARD_TREES;
+          } else if (strcmp((char*)flag, "mining")==0) {
+            rdata->guard |= GUARD_MINING;
+          }
+          xmlFree(flag);
+        }
+      }
+      xmlXPathFreeObject(result);
+
+      /* reading eressea/resources/resource/resourcelimit/function */
+      result = xmlXPathEvalExpression(BAD_CAST "function", xpath);
+      if (result->nodesetval!=NULL) for (k=0;k!=result->nodesetval->nodeNr;++k) {
+        xmlNodePtr node = result->nodesetval->nodeTab[k];
+        pf_generic fun;
+
+        property = xmlGetProp(node, BAD_CAST "value");
+        assert(property!=NULL);
+        fun = get_function((const char*)property);
+        if (fun==NULL) {
+          log_error(("unknown limit '%s' for resource %s\n",
+            (const char*)property, rtype->_name[0]));
+          xmlFree(property);
+          continue;
+        }
+        xmlFree(property);
+
+        property = xmlGetProp(node, BAD_CAST "name");
+        assert(property!=NULL);
+        if (strcmp((const char*)property, "produce")==0) {
+          rdata->produce = (rlimit_produce)fun;
+        } else if (strcmp((const char*)property, "limit")==0) {
+          rdata->limit = (rlimit_limit)fun;
+        } else {
+          log_error(("unknown limit '%s' for resource %s\n",
+            (const char*)property, rtype->_name[0]));
+        }
+        xmlFree(property);
+      }
+    }
+    xmlXPathFreeObject(result);
+
     /* reading eressea/resources/resource/resourcelimit/function */
     xpath->node = node;
     result = xmlXPathEvalExpression(BAD_CAST "resourcelimit/function", xpath);
-    if (result->nodesetval!=NULL) for (k=0;k!=result->nodesetval->nodeNr;++k) {
-      attrib * a = a_find(rtype->attribs, &at_resourcelimit);
-      xmlNodePtr node = result->nodesetval->nodeTab[k];
-      pf_generic fun;
-
-      property = xmlGetProp(node, BAD_CAST "value");
-      assert(property!=NULL);
-      fun = get_function((const char*)property);
-      if (fun==NULL) {
-        log_error(("unknown limit '%s' for resource %s\n",
-          (const char*)property, rtype->_name[0]));
-        xmlFree(property);
-        continue;
-      }
-      xmlFree(property);
-
-      if (a==NULL) a = a_add(&rtype->attribs, a_new(&at_resourcelimit));
-
-      property = xmlGetProp(node, BAD_CAST "name");
-      assert(property!=NULL);
-      if (strcmp((const char*)property, "use")==0) {
-        resource_limit * rdata = (resource_limit*)a->data.v;
-        rdata->use = (rlimit_use)fun;
-      } else if (strcmp((const char*)property, "limit")==0) {
-        resource_limit * rdata = (resource_limit*)a->data.v;
-        rdata->limit = (rlimit_limit)fun;
-      } else {
-        log_error(("unknown limit '%s' for resource %s\n",
-          (const char*)property, rtype->_name[0]));
-      }
-      xmlFree(property);
-    }
     xmlXPathFreeObject(result);
 
     /* reading eressea/resources/resource/item */
@@ -1312,7 +1397,7 @@ parse_races(xmlDocPtr doc)
     rc->maintenance = xml_ivalue(node, "maintenance", 0);
     rc->weight = xml_ivalue(node, "weight", 0);
 #ifdef RACE_CAPACITY
-    rc->capacity = xml_ivalue(node, "capacity", 0);
+    rc->capacity = xml_ivalue(node, "capacity", 540);
 #endif
     rc->speed = (float)xml_fvalue(node, "speed", 1.0F);
     rc->hitpoints = xml_ivalue(node, "hp", 0);
diff --git a/src/common/modules/arena.c b/src/common/modules/arena.c
index 8136ac0e4..eca6abc6b 100644
--- a/src/common/modules/arena.c
+++ b/src/common/modules/arena.c
@@ -235,13 +235,14 @@ make_temple(region * r)
 {
 	const building_type * btype = bt_find("temple");
 	building * b;
-	if (btype==NULL)
-		btype = bt_make("temple", BTF_UNIQUE | BTF_NOBUILD | BTF_INDESTRUCTIBLE, -1, 2, 50);
-	else {
-		b = r->buildings;
-		while (b!=NULL && b->type!=btype) b = b->next;
-		if (b!=NULL) return; /* gibt schon einen */
-	}
+  if (btype==NULL) {
+    log_error(("could not find buildingtype 'temple'\n"));
+    return;
+  }
+
+  b = r->buildings;
+	while (b!=NULL && b->type!=btype) b = b->next;
+	if (b!=NULL) return; /* gibt schon einen */
 
 	b = new_building(btype, r, NULL);
 	b->size = btype->maxsize;
diff --git a/src/common/modules/autoseed.c b/src/common/modules/autoseed.c
index e60d965ea..47d2a32cd 100644
--- a/src/common/modules/autoseed.c
+++ b/src/common/modules/autoseed.c
@@ -487,7 +487,7 @@ autoseed(newfaction ** players, int nsize, boolean new_island)
   short x = 0, y = 0;
   region * r = NULL;
   region_list * rlist = NULL;
-  int rsize, tsize = 0;
+  int rsize = 0, tsize = 0;
   int isize = REGIONS_PER_FACTION; /* target size for the island */
   int psize = 0; /* players on this island */
   const terrain_type * volcano_terrain = get_terrain("volcano");
@@ -567,14 +567,15 @@ autoseed(newfaction ** players, int nsize, boolean new_island)
       assert(virgin_region(rconnect(rmin, dmin)));
       x = rmin->x + delta_x[dmin];
       y = rmin->y + delta_y[dmin];
+      r = new_region(x, y);
+      terraform(r, T_OCEAN); /* we change the terrain later */
     }
-    r = new_region(x, y);
-    terraform(r, T_OCEAN); /* we change the terrain later */
   }
-
-  add_regionlist(&rlist, r);
-  fset(r, FL_MARK);
-  rsize = 1;
+  if (r!=NULL) {
+    add_regionlist(&rlist, r);
+    fset(r, FL_MARK);
+    rsize = 1;
+  }
 
   while (rsize && (nsize || isize>=REGIONS_PER_FACTION)) {
     int i = rand() % rsize;
diff --git a/src/common/modules/gmcmd.c b/src/common/modules/gmcmd.c
index c97635e9b..41d0759df 100644
--- a/src/common/modules/gmcmd.c
+++ b/src/common/modules/gmcmd.c
@@ -706,10 +706,10 @@ gm_addquest(const char * email, const char * name, short radius, unsigned int fl
 
 	a_add((attrib**)&a->data.v, make_atgmcreate(resource2item(r_silver)));
 
-	for (i=0;i<=I_WAGON;++i) {
+	for (i=0;i<=I_HORSE;++i) {
 		a_add((attrib**)&a->data.v, make_atgmcreate(olditemtype[i]));
 	}
-	for (i=I_LAENSWORD;i!=I_DRACHENBLUT;++i) {
+	for (i=I_LAEN;i!=I_DRACHENBLUT;++i) {
 		a_add((attrib**)&a->data.v, make_atgmcreate(olditemtype[i]));
 	}
 
@@ -771,10 +771,10 @@ gm_addfaction(const char * email, plane * p, region * r)
 
 	a_add((attrib**)&a->data.v, make_atgmcreate(resource2item(r_silver)));
 
-	for (i=0;i<=I_WAGON;++i) {
+	for (i=0;i<=I_HORSE;++i) {
 		a_add((attrib**)&a->data.v, make_atgmcreate(olditemtype[i]));
 	}
-	for (i=I_LAENSWORD;i!=I_DRACHENBLUT;++i) {
+	for (i=I_LAEN;i!=I_DRACHENBLUT;++i) {
 		a_add((attrib**)&a->data.v, make_atgmcreate(olditemtype[i]));
 	}
 
diff --git a/src/common/settings-eressea.h b/src/common/settings-eressea.h
index be31c8949..fd2b8abed 100644
--- a/src/common/settings-eressea.h
+++ b/src/common/settings-eressea.h
@@ -17,7 +17,6 @@
 #define ENTERTAINFRACTION 20
 #define IMMUN_GEGEN_ANGRIFF 8
 #define RESOURCE_CONVERSION 1
-#define RACE_ADJUSTMENTS 1
 #define TEACHDIFFERENCE 2
 #define PEASANT_ADJUSTMENT 1
 #define GUARD_DISABLES_RECRUIT 1
diff --git a/src/common/settings-tutorial.h b/src/common/settings-tutorial.h
index 099b5cded..d44677c2f 100644
--- a/src/common/settings-tutorial.h
+++ b/src/common/settings-tutorial.h
@@ -17,7 +17,6 @@
 #define ENTERTAINFRACTION 20
 #define IMMUN_GEGEN_ANGRIFF 8
 #define RESOURCE_CONVERSION 1
-#define RACE_ADJUSTMENTS 1
 #define TEACHDIFFERENCE 2
 #define PEASANT_ADJUSTMENT 1
 #define GUARD_DISABLES_RECRUIT 1
diff --git a/src/common/settings-vinyambar-3.h b/src/common/settings-vinyambar-3.h
index 854beabdc..b233488e6 100644
--- a/src/common/settings-vinyambar-3.h
+++ b/src/common/settings-vinyambar-3.h
@@ -17,7 +17,6 @@
 #define ENTERTAINFRACTION 20
 #define IMMUN_GEGEN_ANGRIFF 8
 #define RESOURCE_CONVERSION 1
-#define RACE_ADJUSTMENTS 1
 #define TEACHDIFFERENCE 2
 #define PEASANT_ADJUSTMENT 1
 #define GUARD_DISABLES_RECRUIT 1
diff --git a/src/common/settings-wdw.h b/src/common/settings-wdw.h
index 723273714..8018ede6f 100644
--- a/src/common/settings-wdw.h
+++ b/src/common/settings-wdw.h
@@ -17,7 +17,6 @@
 #define ENTERTAINFRACTION 20
 #define IMMUN_GEGEN_ANGRIFF 8
 #define RESOURCE_CONVERSION 1
-#define RACE_ADJUSTMENTS 1
 #define TEACHDIFFERENCE 2
 #define PEASANT_ADJUSTMENT 1
 #define GUARD_DISABLES_RECRUIT 1
diff --git a/src/eressea/korrektur.c b/src/eressea/korrektur.c
index 23931662f..18388328a 100644
--- a/src/eressea/korrektur.c
+++ b/src/eressea/korrektur.c
@@ -345,7 +345,7 @@ update_gms(void)
 			for (k=0;keys[k];++k) {
 				add_key((attrib**)&permissions->data.v, atoi36(keys[k]));
 			}
-			for (i=I_LAENSWORD;i!=I_DRACHENBLUT;++i) {
+			for (i=I_LAEN;i!=I_DRACHENBLUT;++i) {
 				attrib * a = a_find((attrib*)permissions->data.v, &at_gmcreate);
 				while (a && a->data.v!=(void*)olditemtype[i]) a=a->nexttype;
 				if (!a) a_add((attrib**)&permissions->data.v, make_atgmcreate(olditemtype[i]));
diff --git a/src/eressea/lua/eressea.cpp b/src/eressea/lua/eressea.cpp
index 2eb62cd9d..37b9695a4 100644
--- a/src/eressea/lua/eressea.cpp
+++ b/src/eressea/lua/eressea.cpp
@@ -182,7 +182,10 @@ lua_autoseed(const char * filename, bool new_island)
     int n = listlen(players);
     int k = (n+ISLANDSIZE-1)/ISLANDSIZE;
     k = n / k;
-    autoseed(&players, k, new_island || (turn % TURNS_PER_ISLAND)==0);
+    n = autoseed(&players, k, new_island || (turn % TURNS_PER_ISLAND)==0);
+    if (n==0) {
+      break;
+    }
   }
 }
 
diff --git a/src/eressea/lua/item.cpp b/src/eressea/lua/item.cpp
index b67be07c3..13ab01648 100644
--- a/src/eressea/lua/item.cpp
+++ b/src/eressea/lua/item.cpp
@@ -4,9 +4,13 @@
 #include "script.h"
 
 // kernel includes
-#include <kernel/unit.h>
 #include <kernel/item.h>
+#include <kernel/region.h>
+#include <kernel/unit.h>
+
+// util includes
 #include <util/attrib.h>
+#include <util/functions.h>
 
 // lua includes
 #include <lua.hpp>
@@ -62,9 +66,58 @@ item_register(const char * name, const char * appearance)
   init_itemnames();
 }
 
+static int
+limit_resource(const region * r, const resource_type * rtype)
+{
+  char fname[64];
+  snprintf(fname, sizeof(fname), "%s_limit", rtype->_name[0]);
+  int retval = -1;
+
+  lua_State * L = (lua_State *)global.vm_state;
+  if (is_function(L, fname)) {
+    try {
+      retval = call_function<int>(L, fname, r);
+    }
+    catch (error& e) {
+      lua_State* L = e.state();
+      const char* error = lua_tostring(L, -1);
+      log_error(("An exception occured while trying to call '%s': %s.\n",
+        fname, error));
+      lua_pop(L, 1);
+      std::terminate();
+    }
+  }
+  return retval;
+}
+
+static void
+produce_resource(region * r, const resource_type * rtype, int norders)
+{
+  char fname[64];
+  snprintf(fname, sizeof(fname), "%s_produce", rtype->_name[0]);
+
+  lua_State * L = (lua_State *)global.vm_state;
+  if (is_function(L, fname)) {
+    try {
+      call_function<void>(L, fname, r, norders);
+    }
+    catch (error& e) {
+      lua_State* L = e.state();
+      const char* error = lua_tostring(L, -1);
+      log_error(("An exception occured while trying to call '%s': %s.\n",
+        fname, error));
+      lua_pop(L, 1);
+      std::terminate();
+    }
+  }
+}
+
 void
 bind_item(lua_State * L) 
 {
+  register_function((pf_generic)produce_resource, "lua_produceresource");
+  register_function((pf_generic)limit_resource, "lua_limitresource");
+
   module(L)[
     def("register_item", &item_register)
   ];
diff --git a/src/eressea/main.c b/src/eressea/main.c
index 235809b63..adb7a1c6e 100644
--- a/src/eressea/main.c
+++ b/src/eressea/main.c
@@ -177,7 +177,6 @@ game_init(void)
   init_races();
   init_itemtypes();
   init_races();
-  init_economy();
   init_rawmaterials();
 
   init_gmcmd();
diff --git a/src/eressea/server.cpp b/src/eressea/server.cpp
index 1fd44349d..c974b5d3c 100644
--- a/src/eressea/server.cpp
+++ b/src/eressea/server.cpp
@@ -245,7 +245,6 @@ game_init(void)
   init_attributes();
   init_races();
   init_itemtypes();
-  init_economy();
   init_rawmaterials();
 
   init_gmcmd();
diff --git a/src/mapper/map_partei.c b/src/mapper/map_partei.c
index f7157f73d..e8fffa283 100644
--- a/src/mapper/map_partei.c
+++ b/src/mapper/map_partei.c
@@ -137,31 +137,6 @@ change_level(unit * u, skill_t sk, int bylevel)
 	sk_set(sv, sv->level+bylevel);
 }
 
-static void
-give_latestart_bonus(region *r, unit *u, int b)
-{
-	int bsk = days2level(b*30);
-	change_level(u, SK_OBSERVATION, bsk);
-	change_money(u, 200*b);
-
-	{
-		unit *u2 = createunit(r, u->faction, 1, u->race);
-		change_level(u2, SK_TACTICS, bsk);
-		u2->irace = u->irace;
-/*		fset(u2, UFL_PARTEITARNUNG); */
-	}
-
-	{
-		unit *u2 = createunit(r, u->faction, 2*b, u->race);
-		change_level(u2, SK_SPEAR, 3);
-		change_level(u2, SK_TAXING, 3);
-		i_change(&u2->items, olditemtype[I_SPEAR], u2->number);
-		u2->irace = u->irace;
-/*		fset(u2, UFL_PARTEITARNUNG); */
-	}
-}
-
-
 newfaction *
 select_newfaction(const struct race * rc)
 {
@@ -318,8 +293,6 @@ NeuePartei(region * r)
 	u = addplayer(r, addfaction(email, passwd, frace, lang, subscription));
 	++numnewbies;
 
-	if(late) give_latestart_bonus(r, u, late);
-
 	sprintf(buf, "newuser %s", email);
 	system(buf);
 }
diff --git a/src/res/equipment.xml b/src/res/equipment.xml
index 654c52af1..ce148018c 100644
--- a/src/res/equipment.xml
+++ b/src/res/equipment.xml
@@ -242,6 +242,17 @@
     <skill name="herbalism" level="d2"/>
   </set>
 
+  <set name="random_villagers">
+    <item name="money" amount="d80+19"/>
+    <skill name="cartmaking" level="d2-1"/>
+    <skill name="mining" level="d2-1"/>
+    <skill name="quarrying" level="d2-1"/>
+    <skill name="forestry" level="d2-1"/>
+    <item name="horse" amount="2"/>
+    <item name="wagon" amount="d2-1"/>
+    <item name="money" amount="d30+10"/>
+  </set>
+
   <set name="random_plain">
     <item name="money" amount="d80+19"/>
     <subset>
diff --git a/src/res/messages.xml b/src/res/messages.xml
index 7c2e91d1b..c53f69cb1 100644
--- a/src/res/messages.xml
+++ b/src/res/messages.xml
@@ -4635,6 +4635,16 @@
     <text locale="fr">"$unit($unit) in $region($region): '$order($command)' - You can breed horses only in a stable."</text>
     <text locale="en">"$unit($unit) in $region($region): '$order($command)' - You can breed horses only in a stable."</text>
   </message>
+  <message name="error121" section="errors">
+    <type>
+      <arg name="unit" type="unit"/>
+      <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="fr">"$unit($unit) in $region($region): '$order($command)' - That resource does not exist in this region."</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>
       <arg name="unit" type="unit"/>
diff --git a/src/res/resources.xml b/src/res/resources.xml
index 6dccb840c..2551bdeab 100644
--- a/src/res/resources.xml
+++ b/src/res/resources.xml
@@ -1,6 +1,43 @@
 <?xml version="1.0"?>
 <resources>
 
+  <resource name="seed" limited="yes">
+    <item weight="10" score="50">
+      <construction skill="herbalism" minskill="3" reqsize="1"/>
+    </item>
+  </resource>
+
+  <resource name="mallornseed" limited="yes">
+    <item weight="10" score="100">
+      <construction skill="herbalism" minskill="4" reqsize="1"/>
+    </item>
+  </resource>
+
+  <resource name="log">
+    <item weight="500" score="10">
+      <construction skill="forestry" minskill="1" reqsize="1"/>
+    </item>
+    <resourcelimit>
+      <modifier building="sawmill" type="skill" value="1"/>
+      <modifier building="sawmill" type="material" value="0.5"/>
+      <guard flag="logging"/>
+      <function name="produce" value="lua_produceresource"/>
+      <function name="limit" value="lua_limitresource"/>
+    </resourcelimit>
+  </resource>
+
+  <resource name="mallorn">
+    <item weight="500" score="30">
+      <construction skill="forestry" minskill="2" reqsize="1"/>
+    </item>
+    <resourcelimit>
+      <bonus building="sawmill" type="skill" value="1"/>
+      <guard flag="logging"/>
+      <function name="produce" value="lua_produceresource"/>
+      <function name="limit" value="lua_limitresource"/>
+    </resourcelimit>
+  </resource>
+
 <!-- luxury items -->
   <resource name="balm">
     <item weight="200"><luxury price="4"/></item>
@@ -54,15 +91,11 @@
   </resource>
 
 <!-- items -->
-  <resource name="seed" limited="yes">
-    <item weight="10" score="50">
-      <construction skill="herbalism" minskill="3" reqsize="1"/>
-    </item>
-  </resource>
-
-  <resource name="mallornseed" limited="yes">
-    <item weight="10" score="100">
-      <construction skill="herbalism" minskill="4" reqsize="1"/>
+  <resource name="cart" big="true">
+    <item capacity="14000" weight="4000" score="60" vehicle="yes">
+      <construction skill="cartmaking" minskill="1" reqsize="1">
+        <requirement type="log" quantity="5"/>
+      </construction>
     </item>
   </resource>
 
@@ -94,8 +127,20 @@
     </item>
   </resource>
 
+  <resource name="laensword">
+    <item weight="100" score="400">
+      <construction skill="weaponsmithing" minskill="8" reqsize="1">
+        <requirement type="laen" quantity="1"/>
+      </construction>
+      <weapon cut="true" skill="melee" offmod="1" defmod="1" magres="0.30">
+        <damage type="rider" value="3d6+10"/>
+        <damage type="footman" value="3d6+10"/>
+      </weapon>
+    </item>
+  </resource>
+
   <resource name="rustygreatsword">
-    <item weight="200">
+    <item weight="200" score="20">
       <construction skill="weaponsmithing" minskill="4" reqsize="1">
         <requirement type="iron" quantity="2"/>
       </construction>
@@ -107,7 +152,7 @@
   </resource>
 
   <resource name="runesword">
-    <item weight="100">
+    <item weight="100" score="2000">
       <weapon minskill="7" cut="true" magical="yes" skill="melee" offmod="2" defmod="2">
         <function name="attack" value="attack_firesword"/>
         <damage type="rider" value="3d10+10"/>
@@ -127,7 +172,7 @@
   </resource>
 
   <resource name="greatsword">
-    <item weight="200">
+    <item weight="200" score="30">
       <construction skill="weaponsmithing" minskill="4" reqsize="1">
         <requirement type="iron" quantity="2"/>
       </construction>
@@ -264,6 +309,20 @@
     </item>
   </resource>
 
+  <resource name="spear">
+    <item weight="100">
+      <construction skill="weaponsmithing" minskill="2" reqsize="1">
+        <requirement type="log" quantity="1"/>
+      </construction>
+      <weapon pierce="true" skill="polearm" offmod="0" defmod="0">
+        <damage type="footman" value="1d10"/>
+        <damage type="rider" value="1d12+2"/>
+        <modifier type="skill" value="1" riding="true" against_riding="true" against_walking="true" offensive="true"/>
+        <modifier type="skill" value="1" walking="true" against_riding="true" against_walking="true" defensive="true"/>
+      </weapon>
+    </item>
+  </resource>
+
   <resource name="mallornspear">
     <item weight="100">
       <construction skill="weaponsmithing" minskill="5" reqsize="1">
@@ -272,6 +331,20 @@
       <weapon pierce="true" skill="polearm" minskill="5" offmod="0" defmod="0" magres="0.15">
         <damage type="footman" value="1d10+1"/>
         <damage type="rider" value="1d12+3"/>
+        <modifier type="skill" value="1" riding="true" against_riding="true" against_walking="true" offensive="true"/>
+        <modifier type="skill" value="1" walking="true" against_riding="true" against_walking="true" defensive="true"/>
+      </weapon>
+    </item>
+  </resource>
+
+  <resource name="lance">
+    <item weight="200">
+      <construction skill="weaponsmithing" minskill="2" reqsize="1">
+        <requirement type="log" quantity="2"/>
+      </construction>
+      <weapon pierce="true" skill="polearm" offmod="0" defmod="-2">
+        <damage type="footman" value="1d5"/>
+        <damage type="rider" value="2d6+5"/>
       </weapon>
     </item>
   </resource>
@@ -283,7 +356,7 @@
       </construction>
       <weapon pierce="true" skill="polearm" minskill="5" offmod="0" defmod="0" magres="0.15">
         <damage type="footman" value="1d5+1"/>
-        <damage type="rider" value="2d6+2"/>
+        <damage type="rider" value="2d6+6"/>
       </weapon>
     </item>
   </resource>
diff --git a/src/scripts/eressea.lua b/src/scripts/eressea.lua
index e8eed57af..a311347c7 100644
--- a/src/scripts/eressea.lua
+++ b/src/scripts/eressea.lua
@@ -31,7 +31,8 @@ function run_scripts()
     "eressea/ponnuki.lua",
     "eressea/xmas2004.lua",
     "eressea/xmas2005.lua",
-    "eressea/embassy.lua"
+    "eressea/embassy.lua",
+    "eressea/ents.lua"
   }
   for index in scripts do
     loadscript(scripts[index])
@@ -66,6 +67,7 @@ function process(orders)
   spawn_dragons()
   spawn_undead()
   spawn_braineaters(0.25)
+  spawn_ents()
 
   plan_monsters()
   process_orders()
diff --git a/src/scripts/eressea/ents.lua b/src/scripts/eressea/ents.lua
new file mode 100644
index 000000000..0133e061f
--- /dev/null
+++ b/src/scripts/eressea/ents.lua
@@ -0,0 +1,33 @@
+
+local function create_ents(r, number)
+  local f = get_faction(0)
+  if f~=nil and number>0 then
+    u = add_unit(f, r)
+    u.number = number
+    u.name = "W�tende Ents"
+    u:set_skill("perception", 2)
+    
+    msg = message("entrise")
+    msg:set_region("region", r)
+    msg:send_region(r)
+    return u
+  end
+  return nil
+end
+
+-- this is old stuff. it's not active at the moment.
+function spawn_ents()
+  local r
+  for r in regions() do
+    if r:get_flag(0) then -- RF_CHAOTIC
+      if r.terrain == "plain" and r:get_resource("tree")==0 then
+        if math.random(3)==1 then
+          u = create_ents(r, math.random(30))
+          if u ~= nil then
+            r:set_resource("tree", u.number)
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/src/scripts/extensions.lua b/src/scripts/extensions.lua
index e9b9d7ded..325283155 100644
--- a/src/scripts/extensions.lua
+++ b/src/scripts/extensions.lua
@@ -28,3 +28,49 @@ function hp_changeresource(u, delta)
   u.hp = hp
   return hp
 end
+
+function log_limit(r)
+  if r:get_flag(1) then -- RF_MALLORN
+    return 0
+  end
+  return r:get_resource("tree") + r:get_resource("sapling")
+end
+
+function log_produce(r, n)
+  local trees = r:get_resource("tree")
+  if trees>=n then
+    r:set_resource("tree", trees-n)
+  else
+    r:set_resource("tree", 0)
+    n = n - trees
+    trees = r:get_resource("sapling")
+    if trees>=n then
+      r:set_resource("sapling", trees-n)
+    else
+      r:set_resource("sapling", 0)
+    end
+  end
+end
+
+function mallorn_limit(r)
+  if not r:get_flag(1) then -- RF_MALLORN
+    return 0
+  end
+  return r:get_resource("tree") + r:get_resource("sapling")
+end
+
+function mallorn_produce(r, n)
+  local trees = r:get_resource("tree")
+  if trees>=n then
+    r:set_resource("tree", trees-n)
+  else
+    r:set_resource("tree", 0)
+    n = n - trees
+    trees = r:get_resource("sapling")
+    if trees>=n then
+      r:set_resource("sapling", trees-n)
+    else
+      r:set_resource("sapling", 0)
+    end
+  end
+end