diff --git a/game/engine/Entity.lua b/game/engine/Entity.lua
index 3023b7e9af1ea1170997cc7af49a875f14734179..0de153a3424232df28e75b5f2bcc72e6c062bf4f 100644
--- a/game/engine/Entity.lua
+++ b/game/engine/Entity.lua
@@ -9,6 +9,21 @@ local next_uid = 1
 -- Setup the uids repository as a weak value table, when the entities are no more used anywhere else they disappear from there too
 setmetatable(__uids, {__mode="v"})
 
+local function copy_recurs(dst, src, deep)
+	for k, e in pairs(src) do
+		if not dst[k] then
+			if deep then
+				dst[k] = {}
+				copy_recurs(dst[k], e, deep)
+			else
+				dst[k] = e
+			end
+		elseif type(dst[k]) == "table" and type(e) == "table" then
+			copy_recurs(dst[k], e, deep)
+		end
+	end
+end
+
 --- Initialize an entity
 -- Any subclass MUST call this constructor
 -- @param t a table defining the basic properties of the entity
@@ -18,7 +33,11 @@ function _M:init(t)
 	self.uid = next_uid
 	__uids[self.uid] = self
 
-	for k, e in pairs(t) do self[k] = e end
+	for k, e in pairs(t) do
+		local ee = e
+		if type(e) == "table" then ee = table.clone(e, true) end
+		self[k] = ee
+	end
 
 	self.image = self.image or nil
 	self.display = self.display or '.'
@@ -62,6 +81,21 @@ function _M:changeUid(newuid)
 	__uids[self.uid] = self
 end
 
+--- Resolves an entity
+-- This is called when generatingthe final clones of an entity for use in a level.<br/>
+-- This can be used to make random enchants on objects, random properties on actors, ...<br/>
+-- by default this only looks for properties with a table value containing a __resolver field
+function _M:resolve(t)
+	t = t or self
+	for k, e in pairs(t) do
+		if type(e) == "table" and e.__resolver then
+			t[k] = resolvers.calc[e.__resolver](e, self)
+		elseif type(e) == "table" then
+			self:resolve(e)
+		end
+	end
+end
+
 --- Check for an entity's property
 -- If not a function it returns it directly, otherwise it calls the function
 -- with the extra parameters
@@ -81,12 +115,40 @@ function _M:loadList(...)
 	for i, file in ipairs{...} do
 		local f, err = loadfile(file)
 		if err then error(err) end
-		local data = f()
-		for i, a in ipairs(data) do
-			local e = self.new(a)
-			res[#res+1] = e
-			if a.define_as then res[a.define_as] = e end
-		end
+
+		setfenv(f, setmetatable({
+			resolvers = resolvers,
+			DamageType = require "engine.DamageType",
+			newEntity = function(t)
+				-- Do we inherit things ?
+				if t.base then
+					for k, e in pairs(res[t.base]) do
+						if not t[k] then
+							t[k] = e
+						elseif type(t[k]) == "table" and type(e) == "table" then
+							copy_recurs(t[k], e)
+						end
+					end
+					t.base = nil
+				end
+
+				local e = self.new(t)
+				res[#res+1] = e
+				if t.define_as then res[t.define_as] = e end
+				print("new entity", t.name)
+				for k, ee in pairs(e) do
+					print("prop:", k, ee)
+				end
+			end,
+			load = function(f)
+				local ret = self:loadList(f)
+				for i, e in ipairs(ret) do res[#res+1] = e end
+			end,
+			loadList = function(f)
+				return self:loadList(f)
+			end,
+		}, {__index=_G}))
+		f()
 	end
 	return res
 end
diff --git a/game/engine/Object.lua b/game/engine/Object.lua
new file mode 100644
index 0000000000000000000000000000000000000000..56eaa2000c8737a698cb3cafa2a3c13a7702a1a6
--- /dev/null
+++ b/game/engine/Object.lua
@@ -0,0 +1,14 @@
+require "engine.class"
+local Entity = require "engine.Entity"
+
+module(..., package.seeall, class.inherit(Entity))
+
+function _M:init(t)
+	t = t or {}
+	Entity.init(self, t)
+end
+
+--- Gets the full name of the object
+function _M:getName()
+	return self.name
+end
diff --git a/game/engine/class.lua b/game/engine/class.lua
index dd430c9b4810a8adf8ce5004f3ec1700d269a4fb..e7f10e3166a476c51a83e7bcebe0f119834eb1a2 100644
--- a/game/engine/class.lua
+++ b/game/engine/class.lua
@@ -32,7 +32,7 @@ function inherit(base, ...)
 				for k, e in pairs(_if) do
 					if k ~= "init" and k ~= "_NAME" and k ~= "_M" and k ~= "_PACKAGE" and k ~= "new" then
 						c[k] = e
-						print(("caching interface value %s (%s) from %s to %s"):format(k, tostring(e), _if._NAME, c._NAME))
+--						print(("caching interface value %s (%s) from %s to %s"):format(k, tostring(e), _if._NAME, c._NAME))
 					end
 				end
 			end
diff --git a/game/engine/generator/actor/Random.lua b/game/engine/generator/actor/Random.lua
index 1719b5862a73952b176693f24eeeac6adb57c0f1..ea129e21505c949e7f8bca5cf398bd61e1eb45b0 100644
--- a/game/engine/generator/actor/Random.lua
+++ b/game/engine/generator/actor/Random.lua
@@ -17,6 +17,7 @@ end
 function _M:generate()
 	for i = 1, rng.range(self.nb_npc[1], self.nb_npc[2]) do
 		local m = self.npc_list[rng.range(1, #self.npc_list)]:clone()
+		m:resolve()
 		local x, y = rng.range(0, self.map.w), rng.range(0, self.map.h)
 		local tries = 0
 		while self.map:checkAllEntities(x, y, "block_move") and tries < 100 do
diff --git a/game/engine/init.lua b/game/engine/init.lua
index b0828d951b83e215930c18f5a98524d30cbeff40..17f1fdfe4be2237bacd30f2e949a76c5e2cec5eb 100644
--- a/game/engine/init.lua
+++ b/game/engine/init.lua
@@ -1,6 +1,9 @@
 -- load some utility functions
 dofile("/engine/utils.lua")
 
+-- load resolver functions for entities cloning
+dofile("/engine/resolvers.lua")
+
 require "config"
 require "engine.KeyCommand"
 require "engine.Savefile"
diff --git a/game/engine/resolvers.lua b/game/engine/resolvers.lua
new file mode 100644
index 0000000000000000000000000000000000000000..f2b3fb2881cc70be8a25d6853aa70ac3e245fa82
--- /dev/null
+++ b/game/engine/resolvers.lua
@@ -0,0 +1,17 @@
+resolvers = {}
+resolvers.calc = {}
+
+--- Resolves a rng range
+function resolvers.rngrange(x, y)
+	return {__resolver="rngrange", x, y}
+end
+function resolvers.calc.rngrange(t)
+	return rng.range(t[1], t[2])
+end
+
+function resolvers.rngavg(x, y)
+	return {__resolver="rngavg", x, y}
+end
+function resolvers.calc.rngavg(t)
+	return rng.avg(t[1], t[2])
+end
diff --git a/game/engine/utils.lua b/game/engine/utils.lua
index 8ae19e95bf5e67ac4909bd9c27cbfaa59a8a6082..e9930339d78a04ba77f72eba77d81750db6f924e 100644
--- a/game/engine/utils.lua
+++ b/game/engine/utils.lua
@@ -1,7 +1,8 @@
 function table.clone(tbl, deep)
 	local n = {}
 	for k, e in pairs(tbl) do
-		if deep and type(e) == "table" then
+		-- Deep copy subtables, but not objects!
+		if deep and type(e) == "table" and not e.__CLASSNAME then
 			n[k] = table.clone(e, true)
 		else
 			n[k] = e
diff --git a/game/modules/tome/data/general/egos.lua b/game/modules/tome/data/general/egos.lua
new file mode 100644
index 0000000000000000000000000000000000000000..4cd504528547d632743dc61c6ed96be4d5a03def
--- /dev/null
+++ b/game/modules/tome/data/general/egos.lua
@@ -0,0 +1,16 @@
+newEntity{
+	name = "flaming ",
+	level_range = {1, 10},
+	rarity = 3,
+	wielder = {
+		melee_project={[DamageType.FIRE] = 4},
+	},
+}
+newEntity{
+	name = " of accuracy",
+	level_range = {1, 10},
+	rarity = 3,
+	wielder = {
+		hit = 4,
+	},
+}
diff --git a/game/modules/tome/data/general/objects.lua b/game/modules/tome/data/general/objects.lua
new file mode 100644
index 0000000000000000000000000000000000000000..6e11c0c1ef04fd0c3aa0d7f7c8a8ea96ec4fb5ac
--- /dev/null
+++ b/game/modules/tome/data/general/objects.lua
@@ -0,0 +1,53 @@
+newEntity{
+	define_as = "BASE_SWORD",
+	type = "weapon",
+	display = "\\", color_r=255,
+	encumber = 3,
+	egos_chance = { },
+	egos = loadList("/data/general/egos.lua"),
+}
+
+newEntity{
+	base = "BASE_SWORD",
+	name = "& #1#longsword~#2#",
+	level_range = {1, 10},
+	rarity = 3,
+	wielder = {
+		combat_dam=resolvers.rngavg(7,11),
+	},
+}
+
+newEntity{
+	name = "& tower shield~",
+	display = "[", color_r=255,
+	level_range = {1, 10},
+	encumber = 6,
+	wielder = {
+		combat_def=6,
+	},
+}
+
+newEntity{
+	name = "& staff~ of fire",
+	type = "weapon",
+	display = "/", color_b=255,
+	level_range = {1, 10},
+	encumber = 4,
+	wielder = {
+		combat_dam=3,
+		stats = {mag=3, wil=2},
+	}
+}
+
+newEntity{
+	name = "& Staff of Olorin",
+	type = "weapon",
+	display = "/", color_r=255, color_b=255,
+	level_range = {10,10},
+	encumber = 3,
+	unique = "STAFF_OLORIN",
+	wielder = {
+		combat_dam=3,
+		stats = {mag=3, wil=2},
+	}
+}
diff --git a/game/modules/tome/data/zones/ancient_ruins/grids.lua b/game/modules/tome/data/zones/ancient_ruins/grids.lua
index 9e09dda1b8a13243b9ee593f9c1da5340228df3d..e553fbe6062e771a627cb877edacde083d0aefe8 100644
--- a/game/modules/tome/data/zones/ancient_ruins/grids.lua
+++ b/game/modules/tome/data/zones/ancient_ruins/grids.lua
@@ -1,43 +1,44 @@
-return {
-
-{
+newEntity{
 	define_as = "UP",
 	name = "previous level",
 	display = '<', color_r=255, color_g=255, color_b=0,
 	change_level = -1
-},
-{
+}
+
+newEntity{
 	define_as = "DOWN",
 	name = "next level",
 	display = '>', color_r=255, color_g=255, color_b=0,
 	change_level = 1
-},
-{
+}
+
+newEntity{
 	define_as = "FLOOR",
 	name = "floor",
 	display = '.', color_r=255, color_g=255, color_b=255,
-},
-{
+}
+
+newEntity{
 	define_as = "WALL",
 	name = "wall",
 	display = '#', color_r=255, color_g=255, color_b=255,
 	block_move = true,
 	block_sight = true,
-},
-{
+}
+
+newEntity{
 	define_as = "DOOR",
 	name = "door",
 	display = '+', color_r=238, color_g=154, color_b=77,
 	block_sight = true,
 	door_opened = "DOOR_OPEN",
-},
-{
+}
+
+newEntity{
 	define_as = "DOOR_OPEN",
 	name = "open door",
 	display = "'", color_r=238, color_g=154, color_b=77,
 	block_move = false,
 	block_sight = false,
 	door_closed = "DOOR",
-},
-
 }
diff --git a/game/modules/tome/data/zones/ancient_ruins/npcs.lua b/game/modules/tome/data/zones/ancient_ruins/npcs.lua
index 4fe00c8144479259da2a45a162360c90bd065507..82a98589ee87d7e6a3a26a560ae37acaeef6ca4b 100644
--- a/game/modules/tome/data/zones/ancient_ruins/npcs.lua
+++ b/game/modules/tome/data/zones/ancient_ruins/npcs.lua
@@ -1,6 +1,4 @@
-return {
-
-{
+newEntity{
 	name = "dragon of death",
 	display = "D", color_r=255,
 	level_range = {1, 10}, exp_worth = 100,
@@ -13,20 +11,19 @@ return {
 	has_blood = true,
 	stats = { str=15, dex=8, mag=12, },
 	combat = { dam=8, atk=10, apr=2, def=4, armor=6},
-},
-{
+}
+
+newEntity{
 	name = "baby dragon",
 	display = "d", color_r=128,
 --	faction = "poorsods",
 	level_range = {1, 4}, exp_worth = 100,
 	autolevel = "caster",
 	ai = "simple",
-	max_life = 30,
+	max_life = resolvers.rngavg(1,100),
 	max_mana = 1000,
 	max_stamina = 1000,
 	energy = { mod=0.3 },
 	has_blood = {nb=3, color={50,255,120}},
 	combat = { dam=5, atk=6, def=2, apr=1, armor=2},
-},
-
-}
\ No newline at end of file
+}
diff --git a/game/modules/tome/data/zones/ancient_ruins/objects.lua b/game/modules/tome/data/zones/ancient_ruins/objects.lua
index 97aeaddb9693cea76493f6bab55c6c575b824967..6e9e5075c3bb87e916daec28104361c33b6006c6 100644
--- a/game/modules/tome/data/zones/ancient_ruins/objects.lua
+++ b/game/modules/tome/data/zones/ancient_ruins/objects.lua
@@ -1,2 +1 @@
-return {
-}
+load("/data/general/objects.lua")