diff --git a/game/engine/Faction.lua b/game/engine/Faction.lua
index 5b80e8045c56f17fa03199ac7f51e29fa64ebf13..83682670b27f5046023b19be5d0c35c6cff4f3e1 100644
--- a/game/engine/Faction.lua
+++ b/game/engine/Faction.lua
@@ -29,8 +29,30 @@ _M.factions = {}
 function _M:add(t)
 	assert(t.name, "no faction name")
 	t.short_name = t.short_name or t.name:lower():gsub(" ", "-")
+	if self.factions[t.short_name] then print("[FACTION] tried to redefine", t.name) return t.short_name end
+
+	local r = {}
 	t.reaction = t.reaction or {}
+	for n, v in pairs(t.reaction) do
+		n = n:lower():gsub(" ", "-")
+		r[n] = v
+	end
+	t.reaction = r
 	self.factions[t.short_name] = t
+	return t.short_name
+end
+
+--- Sets the initial reaction
+-- Static method
+function _M:setInitialReaction(f1, f2, reaction, mutual)
+	-- Faction always like itself
+	if f1 == f2 then return end
+	if not self.factions[f1] then return end
+	if not self.factions[f2] then return end
+	self.factions[f1].reaction[f2] = reaction
+	if mutual then
+		self.factions[f2].reaction[f1] = reaction
+	end
 end
 
 --- Returns the faction definition
diff --git a/game/engine/Zone.lua b/game/engine/Zone.lua
index 5629fb20a87198c6e1417aa09e4d30893a384ce7..14d094d2d2fd6d3dc294bceb214774acf7154a48 100644
--- a/game/engine/Zone.lua
+++ b/game/engine/Zone.lua
@@ -449,9 +449,11 @@ function _M:newLevel(level_data, lev, old_lev, game)
 	local ux, uy, dx, dy, spots = generator:generate(lev, old_lev)
 	spots = spots or {}
 
+	for i = 1, #spots do print("[NEW LEVEL] spot", spots[i].x, spots[i].y, spots[i].type, spots[i].subtype) end
+
 	level.ups = {{x=ux, y=uy}}
 	level.downs = {{x=dx, y=dy}}
-	level.spots = spots or {}
+	level.spots = spots
 
 	-- Generate objects
 	if level_data.generator.object then
diff --git a/game/engine/generator/map/Forest.lua b/game/engine/generator/map/Forest.lua
index db5dabbfab7deb60c739de471c66fa43a1eb035d..7d3f17cdca270489502a8ec62f382e0feaab1a74 100644
--- a/game/engine/generator/map/Forest.lua
+++ b/game/engine/generator/map/Forest.lua
@@ -101,7 +101,7 @@ function _M:addPond(x, y, spots)
 		quadrant(self.do_ponds.size.w, i)
 	end
 
-	spots[#spots+1] = {x=x, y=y, type="pond"}
+	spots[#spots+1] = {x=x, y=y, type="pond", subtype="pond"}
 end
 
 function _M:generate(lev, old_lev)
diff --git a/game/engine/generator/map/Roomer.lua b/game/engine/generator/map/Roomer.lua
index b6cb2248a5d56f665f9cec607dc3f2768936305c..aab0c7e557b97c03d768fe0a0253d110c2810de3 100644
--- a/game/engine/generator/map/Roomer.lua
+++ b/game/engine/generator/map/Roomer.lua
@@ -392,7 +392,7 @@ function _M:generate(lev, old_lev)
 	-- Find out "interresting" spots
 	local spots = {}
 	for i, r in ipairs(rooms) do
-		spots[#spots+1] = {x=rooms[i].cx, y=rooms[i].cy, type="room"}
+		spots[#spots+1] = {x=rooms[i].cx, y=rooms[i].cy, type="room", subtype=rooms[i].room.name}
 	end
 
 	if self.data.edge_entrances then
diff --git a/game/engine/generator/map/Static.lua b/game/engine/generator/map/Static.lua
index 2cf7d957a66ea4122fab1d328a4bbe43215fdf93..e266bf309ac36c83885b7ac55900c955853b7b58 100644
--- a/game/engine/generator/map/Static.lua
+++ b/game/engine/generator/map/Static.lua
@@ -69,14 +69,11 @@ function _M:loadMap(file)
 		addData = function(t)
 			table.merge(self.level.data, t, true)
 		end,
-		checkConnectivity = function(dst, src)
-			self.spots[#self.spots+1] = {x=dst[1], y=dst[2], check_connectivity=src}
-			print("********************************************")
-			print("********************************************")
-			print(dst[1], dst[2], src)
-			print("********************************************")
-			print("********************************************")
-			print("********************************************")
+		checkConnectivity = function(dst, src, type, subtype)
+			self.spots[#self.spots+1] = {x=dst[1], y=dst[2], check_connectivity=src, type=type or "static", subtype=subtype or "static"}
+		end,
+		addSpot = function(dst, type, subtype)
+			self.spots[#self.spots+1] = {x=dst[1], y=dst[2], type=type or "static", subtype=subtype or "static"}
 		end,
 	}
 	setfenv(f, setmetatable(g, {__index=_G}))
diff --git a/game/engine/generator/map/Town.lua b/game/engine/generator/map/Town.lua
index d9a3c17220bb1163dd9f435b10ebc89299265fc0..935818264e85aabd455807ac0b7d015c6575cc52 100644
--- a/game/engine/generator/map/Town.lua
+++ b/game/engine/generator/map/Town.lua
@@ -82,7 +82,7 @@ function _M:Lshape(inner_grids, x1, x2, y1, y2, ix1, ix2, iy1, iy2)
 	end
 end
 
-function _M:building(leaf)
+function _M:building(leaf, spots)
 	local x1, x2 = leaf.rx + rng.range(2, math.max(2, math.floor(leaf.w / 2 - 3))), leaf.rx + leaf.w - rng.range(2, math.max(2, math.floor(leaf.w / 2 - 3)))
 	local y1, y2 = leaf.ry + rng.range(2, math.max(2, math.floor(leaf.h / 2 - 3))), leaf.ry + leaf.h - rng.range(2, math.max(2, math.floor(leaf.h / 2 - 3)))
 	local ix1, ix2, iy1, iy2 = x1 + 2, x2 - 2, y1 + 2, y2 - 2
@@ -117,6 +117,8 @@ function _M:building(leaf)
 --	if rng.percent(self.lshape_chance) then
 --		self:Lshape(inner_grids, x1, x2, y1, y2, ix1, ix2, iy1, iy2)
 --	end
+
+	spots[#spots+1] = {x=math.floor((x1+x2)/2), y=math.floor((y1+y2)/2), type="building", subtype="building"}
 end
 
 function _M:generate(lev, old_lev)
@@ -128,13 +130,13 @@ function _M:generate(lev, old_lev)
 	bsp:partition()
 
 	print("Town gen made ", #bsp.leafs, "BSP leafs")
+	local spots = {}
 	for z, leaf in ipairs(bsp.leafs) do
 		if rng.percent(self.building_chance) then
-			self:building(leaf)
+			self:building(leaf, spots)
 		end
 	end
 
-	local spots = {}
 	local ux, uy, dx, dy
 	if self.data.edge_entrances then
 		ux, uy, dx, dy, spots = self:makeStairsSides(lev, old_lev, self.data.edge_entrances, spots)
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index 586123a8a294627d670c98cbabf22e0558c5bc36..4bf6f08af91a886e3f35e650585345a3564ee014 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -32,6 +32,7 @@ require "engine.interface.ActorQuest"
 require "engine.interface.BloodyDeath"
 require "engine.interface.ActorFOV"
 require "mod.class.interface.Combat"
+local Faction = require "engine.Faction"
 local Map = require "engine.Map"
 
 module(..., package.seeall, class.inherit(
@@ -324,6 +325,11 @@ function _M:TextSizeCategory()
 end
 
 function _M:tooltip()
+	local factcolor, factstate = "#ANTIQUE_WHITE#", "neutral"
+	if self:reactionToward(game.player) < 0 then factcolor, factstate = "#LIGHT_RED#", "hostile"
+	elseif self:reactionToward(game.player) > 0 then factcolor, factstate = "#LIGHT_GREEN#", "friendly"
+	end
+
 	local rank, rank_color = self:TextRank()
 	return ([[%s%s
 Rank: %s%s
@@ -332,7 +338,9 @@ Exp: %d/%d
 #ff0000#HP: %d (%d%%)
 Stats: %d /  %d / %d / %d / %d / %d
 Size: #ANTIQUE_WHITE#%s
-%s]]):format(
+%s
+Faction: %s%s (%s)
+]]):format(
 	rank_color, self.name,
 	rank_color, rank,
 	self.level,
@@ -346,7 +354,8 @@ Size: #ANTIQUE_WHITE#%s
 	self:getCun(),
 	self:getCon(),
 	self:TextSizeCategory(),
-	self.desc or ""
+	self.desc or "",
+	factcolor, Faction.factions[self.faction].name, factstate
 	)
 end
 
diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index c27d5dd84c75b1a40461b4f08d9120970f2630c7..5420fbde27a2c082217261e07bc1f3fd7e5c7a58 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -419,7 +419,7 @@ function _M:targetMode(v, msg, co, typ)
 	self.target_mode = v
 
 	if not v then
-		Map:setViewerFaction(self.always_target and "players" or nil)
+		Map:setViewerFaction(self.always_target and self.player.faction or nil)
 		if msg then self.log(type(msg) == "string" and msg or "Tactical display disabled. Press shift+'t' or right mouse click to enable.") end
 		self.level.map.changed = true
 		self.target:setActive(false)
@@ -435,7 +435,7 @@ function _M:targetMode(v, msg, co, typ)
 			end
 		end
 	else
-		Map:setViewerFaction("players")
+		Map:setViewerFaction(self.player.faction)
 		if msg then self.log(type(msg) == "string" and msg or "Tactical display enabled. Press shift+'t' to disable.") end
 		self.level.map.changed = true
 		self.target:setActive(true, typ)
@@ -692,7 +692,7 @@ function _M:setupCommands()
 				Map:setViewerFaction(nil)
 			else
 				self.always_target = true
-				Map:setViewerFaction("players")
+				Map:setViewerFaction(self.player.faction)
 			end
 		end,
 
diff --git a/game/modules/tome/class/NPC.lua b/game/modules/tome/class/NPC.lua
index 5a1b0b053b6463a7069d34537027d759686a2d10..14ded8e3cac629cca6f6e502158d4d03c47a4b6a 100644
--- a/game/modules/tome/class/NPC.lua
+++ b/game/modules/tome/class/NPC.lua
@@ -57,18 +57,11 @@ function _M:onTakeHit(value, src)
 end
 
 function _M:tooltip()
-	local factcolor, factstate = "#ANTIQUE_WHITE#", "neutral"
-	if self:reactionToward(game.player) < 0 then factcolor, factstate = "#LIGHT_RED#", "hostile"
-	elseif self:reactionToward(game.player) > 0 then factcolor, factstate = "#LIGHT_GREEN#", "friendly"
-	end
-
 	local str = mod.class.Actor.tooltip(self)
 	return str..([[
 
-Faction: %s%s (%s)
 Target: %s
 UID: %d]]):format(
-	factcolor, Faction.factions[self.faction].name, factstate,
 	self.ai_target.actor and self.ai_target.actor.name or "none",
 	self.uid)
 end
diff --git a/game/modules/tome/data/birth/classes/mage.lua b/game/modules/tome/data/birth/classes/mage.lua
index 2fc01eaab65895cfd201842b6b31d054742adfde..b5ba89e95ccae5fbc83b39555f325280b2f9221d 100644
--- a/game/modules/tome/data/birth/classes/mage.lua
+++ b/game/modules/tome/data/birth/classes/mage.lua
@@ -35,6 +35,8 @@ newBirthDescriptor{
 	},
 	talents = { [ActorTalents.T_TELEPORT_ANGOLWEN]=1 },
 	copy = {
+		-- All mages are of angolwen faction
+		faction = "angolwen",
 		mana_regen = 0.5,
 		mana_rating = 10,
 		resolvers.generic(function(e)
diff --git a/game/modules/tome/data/birth/races/dwarf.lua b/game/modules/tome/data/birth/races/dwarf.lua
index b29a34feb3d0ed8daf1e5e405c9b066578d48f8c..0fce19eaa6ea5fc3c07a461d336ed1d395dc09c4 100644
--- a/game/modules/tome/data/birth/races/dwarf.lua
+++ b/game/modules/tome/data/birth/races/dwarf.lua
@@ -46,6 +46,7 @@ newBirthDescriptor{
 		[ActorTalents.T_DWARF_RESILIENCE]=1,
 	},
 	copy = {
+		faction = "lonely-mountain",
 		type = "humanoid", subtype="dwarf",
 		default_wilderness = {39, 17},
 		starting_zone = "tower-amon-sul",
diff --git a/game/modules/tome/data/birth/races/elf.lua b/game/modules/tome/data/birth/races/elf.lua
index 4cbbb45a58734aaea96299a557c3a74724daaeaa..3184f5db1ec52377f8fb95eca8a61cfcbce396fa 100644
--- a/game/modules/tome/data/birth/races/elf.lua
+++ b/game/modules/tome/data/birth/races/elf.lua
@@ -41,6 +41,7 @@ newBirthDescriptor{
 --		[ActorTalents.T_IMPROVED_MANA_I]=1,
 	},
 	copy = {
+		faction = "eryn-lasgalen",
 		type = "humanoid", subtype="elf",
 		default_wilderness = {39, 17},
 		starting_zone = "tower-amon-sul",
diff --git a/game/modules/tome/data/birth/races/hobbit.lua b/game/modules/tome/data/birth/races/hobbit.lua
index da192401536d409430d353d2e9830ae2c8d6595f..2075e696d1cc775843ecdb705bd713106aaa0f25 100644
--- a/game/modules/tome/data/birth/races/hobbit.lua
+++ b/game/modules/tome/data/birth/races/hobbit.lua
@@ -42,6 +42,7 @@ newBirthDescriptor{
 		[ActorTalents.T_HOBBIT_LUCK]=1,
 	},
 	copy = {
+		faction = "shire",
 		type = "humanoid", subtype="hobbit",
 		life_rating = 12,
 		default_wilderness = {39, 17},
diff --git a/game/modules/tome/data/birth/races/human.lua b/game/modules/tome/data/birth/races/human.lua
index 2afd9386f449d8bf7861db67647b71b67b65acea..cce1012a0917f6726687cf24525db98f4e955002 100644
--- a/game/modules/tome/data/birth/races/human.lua
+++ b/game/modules/tome/data/birth/races/human.lua
@@ -40,6 +40,7 @@ newBirthDescriptor{
 	talents = {},
 	experience = 1.0,
 	copy = {
+		faction = "reunited-kingdom",
 		type = "humanoid", subtype="human",
 	},
 }
diff --git a/game/modules/tome/data/birth/races/orc.lua b/game/modules/tome/data/birth/races/orc.lua
index 0770897ffc0c1519abce9432cbc5c2c06201b176..d106fe057efe35b89e854a35601f621e152d6e64 100644
--- a/game/modules/tome/data/birth/races/orc.lua
+++ b/game/modules/tome/data/birth/races/orc.lua
@@ -50,6 +50,7 @@ newBirthDescriptor{
 		[ActorTalents.T_ORC_FURY]=1,
 	},
 	copy = {
+		faction = "orc-pride",
 		type = "humanoid", subtype="orc",
 		default_wilderness = {10, 39},
 		starting_zone = "wilderness-arda-fareast",
diff --git a/game/modules/tome/data/birth/races/troll.lua b/game/modules/tome/data/birth/races/troll.lua
index 0680dcf65ab9bcbab9cf2e28cd01761fcb65d1ac..44186e30df1104f8223d7b3a9d305cc35d5fe5d7 100644
--- a/game/modules/tome/data/birth/races/troll.lua
+++ b/game/modules/tome/data/birth/races/troll.lua
@@ -44,6 +44,7 @@ newBirthDescriptor{
 --		[ActorTalents.T_DWARF_RESILIENCE]=1,
 	},
 	copy = {
+		faction = "orc-pride",
 		type = "humanoid", subtype="troll",
 		default_wilderness = {39, 17},
 		starting_zone = "tower-amon-sul",
diff --git a/game/modules/tome/data/birth/races/undead.lua b/game/modules/tome/data/birth/races/undead.lua
index 079196ec2fbb0242834dba2c23da3c6b93e53598..d03b9d2aa16e42b800759d902a982517857861f4 100644
--- a/game/modules/tome/data/birth/races/undead.lua
+++ b/game/modules/tome/data/birth/races/undead.lua
@@ -39,6 +39,7 @@ newBirthDescriptor{
 		},
 	},
 	copy = {
+		faction = "players",
 		undead = 1,
 	}
 }
diff --git a/game/modules/tome/data/birth/sexes.lua b/game/modules/tome/data/birth/sexes.lua
index 6c2f6f773cf904aea612ce38ba50211fce261649..1824228c03be7e5cac5d6959f7ba98d3cdf30055 100644
--- a/game/modules/tome/data/birth/sexes.lua
+++ b/game/modules/tome/data/birth/sexes.lua
@@ -26,7 +26,7 @@ newBirthDescriptor{
 		"You are a female of the species.",
 		"There is no in-game difference between the two sexes.",
 	},
-	data = { female=true, },
+	copy = { female=true, },
 }
 
 newBirthDescriptor{
@@ -37,5 +37,5 @@ newBirthDescriptor{
 		"You are a male of the species.",
 		"There is no in-game difference between the two sexes.",
 	},
-	flags = { male=true, },
+	copy = { male=true, },
 }
diff --git a/game/modules/tome/data/factions.lua b/game/modules/tome/data/factions.lua
new file mode 100644
index 0000000000000000000000000000000000000000..791027261b46b1b289c06fae5427f2ddaaab0935
--- /dev/null
+++ b/game/modules/tome/data/factions.lua
@@ -0,0 +1,71 @@
+-- ToME - Tales of Middle-Earth
+-- Copyright (C) 2009, 2010 Nicolas Casalini
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+-- Nicolas Casalini "DarkGod"
+-- darkgod@te4.org
+
+-- CSV export
+local src = [[
+,Enemies,,Reunited Kingdom,Shire,Lonely Mountain,Eryn Lasgalen,Angolwen,Tol Falas,,Water lair|H,Assassin lair|H,,Sunwall,Orc Pride
+Enemies,,,,,,,,,,,,,,
+,,,,,,,,,,,,,,
+Reunited Kingdom,-1,,,,,,,,,,,,,
+Shire,-1,,1,,,,,,,,,,,
+Lonely Mountain,-1,,0.5,1,,,,,,,,,,
+Eryn Lasgalen,-1,,0.5,1,0.3,,,,,,,,,
+Angolwen,-1,,,,,,,,,,,,,
+Tol Falas,,,-1,-1,-1,-1,-1,,,,,,,
+,,,,,,,,,,,,,,
+Water lair|H,-1,,,,,,,,,,,,,
+Assassin lair|H,,,,,,,,,,,,,,
+,,,,,,,,,,,,,,
+Sunwall,-1,,,,,,0,-1,,,-1,,,
+Orc Pride,,,-1,-1,-1,-1,-1,-1,,,,,-1,
+]]
+
+local facts = {}
+local factsid = {}
+local lines = src:split("\n")
+for i, line in ipairs(lines) do
+	local data = line:split(",")
+	for j, d in ipairs(data) do
+
+		if i == 1 then
+			if d ~= "" then
+				local def = d:split("|")
+				local on_attack = false
+				for z = 2, #def do if def[z] == "H" then on_attack = true end end
+
+				local sn = engine.Faction:add{ name=def[1], reaction={}, hostile_on_attack=on_attack }
+				print("[FACTION] added", sn, def[1])
+				facts[sn] = {id=j, reactions={}}
+				factsid[j] = sn
+			end
+		else
+			local n = tonumber(d)
+			if n then
+				facts[factsid[j]].reactions[factsid[i]] = n * 100
+			end
+		end
+	end
+end
+
+for f1, data in pairs(facts) do
+	for f2, v in pairs(data.reactions) do
+		print("[FACTION] initial reaction", f1, f2, " => ", v)
+		engine.Faction:setInitialReaction(f1, f2, v, true)
+	end
+end
diff --git a/game/modules/tome/data/general/encounters/arda-west.lua b/game/modules/tome/data/general/encounters/arda-west.lua
index 5c6b32826ca0d600ec3aad3a4707838a0bd727fc..6038a0ac7c4374e320f97587c77fd0248931473b 100644
--- a/game/modules/tome/data/general/encounters/arda-west.lua
+++ b/game/modules/tome/data/general/encounters/arda-west.lua
@@ -42,7 +42,7 @@ newEntity{
 
 		local g = mod.class.NPC.new{
 			name="Novice mage",
-			type="humanoid", subtype="elf", faction="players",
+			type="humanoid", subtype="elf", faction="angolwen",
 			display='@', color=colors.RED,
 			can_talk = "mage-apprentice-quest",
 		}
@@ -102,7 +102,7 @@ newEntity{
 							},
 						},
 						post_process = function(level)
-							for uid, e in pairs(level.entities) do if e.faction ~= "players" then e.faction="assassin-lair" end end
+							for uid, e in pairs(level.entities) do if e.faction ~= "reunited-kingdom" then e.faction="assassin-lair" end end
 						end,
 					}, },
 
diff --git a/game/modules/tome/data/general/npcs/human-town.lua b/game/modules/tome/data/general/npcs/human-town.lua
new file mode 100644
index 0000000000000000000000000000000000000000..7f7ebf9f6a5b78ff4c2b030b376dd1409105e649
--- /dev/null
+++ b/game/modules/tome/data/general/npcs/human-town.lua
@@ -0,0 +1,69 @@
+-- ToME - Tales of Middle-Earth
+-- Copyright (C) 2009, 2010 Nicolas Casalini
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+-- Nicolas Casalini "DarkGod"
+-- darkgod@te4.org
+
+local Talents = require("engine.interface.ActorTalents")
+
+newEntity{
+	define_as = "BASE_NPC_HUMAN_TOWN",
+	type = "humanoid", subtype = "human",
+	display = "p", color=colors.WHITE,
+	faction = "sunwall",
+
+	combat = { dam=resolvers.rngavg(1,2), atk=2, apr=0, dammod={str=0.4} },
+
+	body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1, QUIVER=1 },
+	resolvers.drops{chance=20, nb=1, {} },
+
+	life_rating = 10,
+	rank = 2,
+	size_category = 3,
+
+	open_door = true,
+
+	autolevel = "warrior",
+	ai = "dumb_talented_simple", ai_state = { talent_in=3, },
+	energy = { mod=1 },
+	stats = { str=12, dex=8, mag=6, con=10 },
+}
+
+newEntity{ base = "BASE_NPC_HUMAN_TOWN",
+	name = "human guard", color=colors.LIGHT_UMBER,
+	desc = [[A stern looking guard, he will not let you disturb the town.]],
+	level_range = {1, 50}, exp_worth = 1,
+	rarity = 4,
+	max_life = resolvers.rngavg(70,80),
+	resolvers.equip{
+		{type="weapon", subtype="longsword", autoreq=true},
+		{type="armor", subtype="shield", autoreq=true},
+	},
+	combat_armor = 2, combat_def = 0,
+	resolvers.talents{ [Talents.T_RUSH]=1, [Talents.T_PERFECT_STRIKE]=1, },
+}
+
+newEntity{ base = "BASE_NPC_HUMAN_TOWN",
+	name = "human archer", color=colors.UMBER,
+	desc = [[A stern looking guard, he will not let you disturb the town.]],
+	level_range = {1, 50}, exp_worth = 1,
+	rarity = 7,
+	max_life = resolvers.rngavg(50,60),
+	resolvers.talents{ [Talents.T_SHOOT]=1, },
+	ai_state = { talent_in=2, },
+	autolevel = "archer",
+	resolvers.equip{ {type="weapon", subtype="longbow", autoreq=true}, {type="ammo", subtype="arrow", autoreq=true} },
+}
diff --git a/game/modules/tome/data/general/npcs/orc.lua b/game/modules/tome/data/general/npcs/orc.lua
index b94debb8421f2b412ee25d701aa4d9f0ceaf2a90..4e19d5f5c7940dabb8b08820ea0bae3271c1431e 100644
--- a/game/modules/tome/data/general/npcs/orc.lua
+++ b/game/modules/tome/data/general/npcs/orc.lua
@@ -23,6 +23,7 @@ newEntity{
 	define_as = "BASE_NPC_ORC",
 	type = "humanoid", subtype = "orc",
 	display = "o", color=colors.UMBER,
+	faction = "orc-pride",
 
 	combat = { dam=resolvers.rngavg(5,12), atk=2, apr=6, physspeed=2 },
 
diff --git a/game/modules/tome/data/maps/quests/lost-merchant.lua b/game/modules/tome/data/maps/quests/lost-merchant.lua
index 448a3d5c259e02f10e92e95afc725e873c680f79..1b2f8573e539f59280bf89c0dcd30e27f04d53e9 100644
--- a/game/modules/tome/data/maps/quests/lost-merchant.lua
+++ b/game/modules/tome/data/maps/quests/lost-merchant.lua
@@ -71,7 +71,7 @@ defineTile('@', "FLOOR", nil, mod.class.NPC.new{
 	name = "Lost Merchant",
 	size_category = 3,
 	ai = "simple",
-	faction = "players",
+	faction = "reunited-kingdom",
 	is_merchant = true,
 })
 
diff --git a/game/modules/tome/data/maps/zones/tower-amon-sul-last.lua b/game/modules/tome/data/maps/zones/tower-amon-sul-last.lua
index 6f5f4899a5b598a3d86467062c11c95a8ebc568c..10f3bd54a6eb0a9f342b74f59064eef35ae85a31 100644
--- a/game/modules/tome/data/maps/zones/tower-amon-sul-last.lua
+++ b/game/modules/tome/data/maps/zones/tower-amon-sul-last.lua
@@ -39,7 +39,7 @@ subGenerator{
 	define_up = true,
 }
 
-checkConnectivity({26,44}, "entrance")
+checkConnectivity({26,44}, "entrance", "boss-area", "boss-area")
 
 return {
 [[                                                  ]],
diff --git a/game/modules/tome/data/talents/spells/nature.lua b/game/modules/tome/data/talents/spells/nature.lua
index 1dcc32135db7af471aebf2c492186055aeec0e26..00a5cfb47ac2c01615ef771ab6ac5b53cbe2e8d3 100644
--- a/game/modules/tome/data/talents/spells/nature.lua
+++ b/game/modules/tome/data/talents/spells/nature.lua
@@ -118,7 +118,7 @@ newTalent{
 		local bear = NPC.new{
 			type = "animal", subtype = "bear",
 			display = "q", color=colors.LIGHT_GREEN,
-			name = "guardian bear", faction = "players",
+			name = "guardian bear", faction = self.faction,
 			desc = [[A bear summoned by the powers of nature to help you.]],
 			autolevel = "warrior",
 			ai = "summoned", ai_real = "dumb_talented_simple", ai_state = { talent_in=3, },
diff --git a/game/modules/tome/data/zones/tol-falas/zone.lua b/game/modules/tome/data/zones/tol-falas/zone.lua
index aa3905a0912a580f8933241c4bfcef60bf6d53ee..53c2ff9d0f586255321e73c52e89e3bfc1a086ef 100644
--- a/game/modules/tome/data/zones/tol-falas/zone.lua
+++ b/game/modules/tome/data/zones/tol-falas/zone.lua
@@ -56,6 +56,9 @@ return {
 			nb_trap = {6, 9},
 		},
 	},
+	post_process = function(level)
+		for uid, e in pairs(level.entities) do e.faction="tol-falas" end
+	end,
 	levels =
 	{
 		[1] = {
diff --git a/game/modules/tome/data/zones/town-sunwall-outpost/npcs.lua b/game/modules/tome/data/zones/town-sunwall-outpost/npcs.lua
index 82f2444fc95fc2babd498e489ddf6df8a60a6198..a6ce4e3eb9db35920b014262256343c82da93fef 100644
--- a/game/modules/tome/data/zones/town-sunwall-outpost/npcs.lua
+++ b/game/modules/tome/data/zones/town-sunwall-outpost/npcs.lua
@@ -17,3 +17,4 @@
 -- Nicolas Casalini "DarkGod"
 -- darkgod@te4.org
 
+load("/data/general/npcs/human-town.lua")
diff --git a/game/modules/tome/data/zones/town-sunwall-outpost/zone.lua b/game/modules/tome/data/zones/town-sunwall-outpost/zone.lua
index f8252906c01a076116ec6c0736d7a351e451f9cc..66317dc6bf5d16502987dc0f7e47f1b7950cecdc 100644
--- a/game/modules/tome/data/zones/town-sunwall-outpost/zone.lua
+++ b/game/modules/tome/data/zones/town-sunwall-outpost/zone.lua
@@ -41,7 +41,7 @@ return {
 		},
 		actor = {
 			class = "engine.generator.actor.Random",
-			nb_npc = {0, 0},
+			nb_npc = {20, 30},
 		},
 		object = {
 			class = "engine.generator.object.Random",
diff --git a/game/modules/tome/load.lua b/game/modules/tome/load.lua
index 464b82a89003a76c9a774a4f01815d7b91e0857d..798a2335740c3c82177f24c7c729080fc319e52c 100644
--- a/game/modules/tome/load.lua
+++ b/game/modules/tome/load.lua
@@ -90,8 +90,7 @@ ActorStats:defineStat("Luck",		"lck", 50, 1, 100, "Luck defines your character's
 ActorLevel:defineMaxLevel(75)
 
 -- Factions
-Faction:add{ name="water lair", reaction={}, hostile_on_attack=true }
-Faction:add{ name="assassin lair", reaction={}, hostile_on_attack=true }
+dofile("/data/factions.lua")
 
 -- Actor autolevel schemes
 dofile("/data/autolevel_schemes.lua")
diff --git a/ideas/factions.ods b/ideas/factions.ods
index 4bf3b06d0dd84e663a7a07fe7150c77335640dd6..5abf3359f00f9c717db20fc2aa657ae7d176d1d5 100644
Binary files a/ideas/factions.ods and b/ideas/factions.ods differ
diff --git a/ideas/technics.ods b/ideas/technics.ods
index c672a36678fefac3d09af5d2e2bb6b531f9d5f88..349460d0e04e062cff8f42a2e6cc63bcc77001ef 100644
Binary files a/ideas/technics.ods and b/ideas/technics.ods differ