diff --git a/game/engine/Actor.lua b/game/engine/Actor.lua
index e11dddb6b8fe5d8d6b85cfbbc37171ab6eaa848f..e60aaa939764263f90243cdcf73cf2834aedf84b 100644
--- a/game/engine/Actor.lua
+++ b/game/engine/Actor.lua
@@ -57,6 +57,7 @@ function _M:move(x, y, force)
 	if y >= map.h then y = map.h - 1 end
 	self.x, self.y = x, y
 	map(x, y, Map.ACTOR, self)
+	map:checkAllEntities(x, y, "on_move", self)
 	game.level:idleProcessActor(self)
 
 	return true
diff --git a/game/engine/Entity.lua b/game/engine/Entity.lua
index 3c22beda91bf2c330047968cc0f49bf884f01ea5..1cdb0f86670c6df0acbd1591675538fd0ca32f5f 100644
--- a/game/engine/Entity.lua
+++ b/game/engine/Entity.lua
@@ -171,11 +171,14 @@ function _M:loadList(file, no_default, res)
 	if entities_load_functions[file] and entities_load_functions[file][no_default] then
 		print("Loading entities file from memory", file)
 		f = entities_load_functions[file][no_default]
-	else
+	elseif fs.exists(file) then
 		f, err = loadfile(file)
 		print("Loading entities file from file", file)
 		entities_load_functions[file] = entities_load_functions[file] or {}
 		entities_load_functions[file][no_default] = f
+	else
+		-- No data
+		f = function() end
 	end
 	if err then error(err) end
 
diff --git a/game/engine/Map.lua b/game/engine/Map.lua
index 74875255e28f255066fa3e7c510a81e7ab0ad9fa..87e456822f32f42fa1d342290bf65a61e2b6650a 100644
--- a/game/engine/Map.lua
+++ b/game/engine/Map.lua
@@ -9,15 +9,15 @@ module(..., package.seeall, class.make)
 
 --- The place of a terrain entity in a map grid
 TERRAIN = 1
+--- The place of a terrain entity in a map grid
+TRAP = 50
 --- The place of an actor entity in a map grid
 ACTOR = 100
 --- The place of an object entity in a map grid
 OBJECT = 1000
 
 --- The order of display for grid seen
-displayOrder = { ACTOR, OBJECT, TERRAIN }
---- The order of display for grids remembered
-rememberDisplayOrder = { TERRAIN }
+searchOrder = { TERRAIN, TRAP, OBJECT, ACTOR }
 
 --- Sets the viewport size
 -- Static
@@ -128,7 +128,7 @@ function _M:loaded()
 	self._fov_lite = core.fov.new(_M.opaque, _M.applyLite, self)
 	self._fov_esp = core.fov.new(_M.opaqueESP, _M.applyESP, self)
 	self.changed = true
-	self.loaded = true
+	self.finished = true
 
 	self:redisplay()
 end
@@ -206,8 +206,17 @@ function _M:updateMap(x, y)
 	local g = self(x, y, TERRAIN)
 	local o = self(x, y, OBJECT)
 	local a = self(x, y, ACTOR)
+	local t = self(x, y, TRAP)
 
 	if g then g = self.tiles:get(g.display, g.color_r, g.color_g, g.color_b, g.color_br, g.color_bg, g.color_bb, g.image) end
+	if t then
+		-- Handles invisibility and telepathy and other such things
+		if not self.actor_player or t:knownBy(self.actor_player) then
+			t = self.tiles:get(t.display, t.color_r, t.color_g, t.color_b, t.color_br, t.color_bg, t.color_bb, t.image)
+		else
+			t = nil
+		end
+	end
 	if o then o = self.tiles:get(o.display, o.color_r, o.color_g, o.color_b, o.color_br, o.color_bg, o.color_bb, o.image) end
 	if a then
 		-- Handles invisibility and telepathy and other such things
@@ -218,7 +227,7 @@ function _M:updateMap(x, y)
 		end
 	end
 
-	self._map:setGrid(x, y, g, o, a)
+	self._map:setGrid(x, y, g, t, o, a)
 end
 
 --- Sets/gets a value from the map
diff --git a/game/engine/Trap.lua b/game/engine/Trap.lua
new file mode 100644
index 0000000000000000000000000000000000000000..f7a1da48e5ed4aa0a206d1e3d9c386069a533fce
--- /dev/null
+++ b/game/engine/Trap.lua
@@ -0,0 +1,146 @@
+require "engine.class"
+local Entity = require "engine.Entity"
+
+--- Describes a trap
+module(..., package.seeall, class.inherit(Entity))
+
+function _M:init(t, no_default)
+	t = t or {}
+
+	assert(t.triggered, "no trap triggered action")
+
+	Entity.init(self, t, no_default)
+
+	if self.disarmable == nil then
+		self.disarmable = true
+	end
+
+	self.known_by = {}
+	self:loaded()
+end
+
+function _M:loaded()
+	-- known_by table is a weak table on keys, so taht it does not prevent garbage collection of actors
+	setmetatable(self.known_by, {__mode="k"})
+end
+
+--- Setup the trap
+function _M:setup()
+end
+
+--- Set the known status for the given actor
+function _M:setKnown(actor, v)
+	self.known_by[actor] = v
+end
+
+--- Get the known status for the given actor
+function _M:knownBy(actor)
+	print("actor", actor.name, "knows", self.name)
+	return self.known_by[actor]
+end
+
+--- Try to disarm the trap
+function _M:disarm(x, y, who)
+	if not self.disarmable then return false end
+end
+
+--- Trigger the trap
+function _M:trigger(x, y, who)
+	if not self.message then
+		game.logSeen(who, "%s triggers a trap (%s)!", who.name:capitalize(), self.name)
+	else
+		local tname = who.name
+		local str =self.message
+		str = str:gsub("@target@", tname)
+		str = str:gsub("@Target@", tname:capitalize())
+		game.logSeen(who, "%s", str)
+	end
+	if self:triggered(x, y, who) then
+		self:knownBy(who, true)
+		game.level.map:updateMap(x, y)
+	end
+end
+
+--- When moving on a trap, trigger it
+function _M:on_move(x, y, who)
+	self:trigger(x, y, who)
+end
+
+--[=[
+require "engine.class"
+local Entity = require "engine.Entity"
+
+--- Describes a trap
+module(..., package.seeall, class.inherit(Entity))
+
+function _M:init(t, no_default)
+	t = t or {}
+
+	assert(t.triggered, "no trap triggered action")
+
+	Entity.init(self, t, no_default)
+
+	if self.disarmable == nil then
+		self.disarmable = true
+	end
+
+	self.known_by_list = {}
+	self:loaded()
+end
+
+function _M:loaded()
+	-- known_by table is a weak table on keys, so taht it does not prevent garbage collection of actors
+	self.known_by = {}
+	setmetatable(self.known_by, {__mode="k"})
+	setmetatable(self.known_by_list, {__mode="v"})
+
+	-- Restore
+	for i, a in ipairs(self.known_by_list) self.known_by[a] = true end
+end
+
+--- Setup the trap
+function _M:setup()
+end
+
+--- Set the known status for the given actor
+function _M:setKnown(actor)
+	print("actor", actor.name, "knows", self.name)
+	if not self.known_by[actor] then
+		self.known_by[actor] = true
+		table.insert(self.known_by_list, actor)
+	end
+end
+
+--- Get the known status for the given actor
+function _M:knownBy(actor)
+	return self.known_by[actor]
+end
+
+--- Try to disarm the trap
+function _M:disarm(x, y, who)
+	if not self.disarmable then return false end
+end
+
+--- Trigger the trap
+function _M:trigger(x, y, who)
+	if not self.message then
+		game.logSeen(who, "%s triggers a trap (%s)!", who.name:capitalize(), self.name)
+	else
+		local tname = who.name
+		local str =self.message
+		str = str:gsub("@target@", tname)
+		str = str:gsub("@Target@", tname:capitalize())
+		game.logSeen(who, "%s", str)
+	end
+	if self:triggered(x, y, who) then
+		self.known_by[who.uid] = true
+		game.level.map:updateMap(x, y)
+	end
+end
+
+--- When moving on a trap, trigger it
+function _M:on_move(x, y, who)
+	self:trigger(x, y, who)
+end
+
+--]=]
\ No newline at end of file
diff --git a/game/engine/Zone.lua b/game/engine/Zone.lua
index 2e27e7a9d4b68ccb0f3d29a84df405efdffb7e96..4fc534748200b03f90dd24cbddeb500b77681886 100644
--- a/game/engine/Zone.lua
+++ b/game/engine/Zone.lua
@@ -16,6 +16,7 @@ function _M:setup(t)
 	self.level_class = require(t.level_class or "engine.Level")
 	self.npc_class = require(t.npc_class or "engine.Actor")
 	self.grid_class = require(t.grid_class or "engine.Grid")
+	self.trap_class = require(t.trap_class or "engine.Trap")
 	self.object_class = require(t.object_class or "engine.Object")
 end
 
@@ -32,6 +33,7 @@ function _M:init(short_name)
 	self.npc_list = self.npc_class:loadList("/data/zones/"..self.short_name.."/npcs.lua")
 	self.grid_list = self.grid_class:loadList("/data/zones/"..self.short_name.."/grids.lua")
 	self.object_list = self.object_class:loadList("/data/zones/"..self.short_name.."/objects.lua")
+	self.trap_list = self.trap_class:loadList("/data/zones/"..self.short_name.."/traps.lua")
 
 	-- Determine a zone base level
 	self.base_level = self.level_range[1]
@@ -157,6 +159,7 @@ function _M:makeEntityByName(level, type, name)
 	if type == "actor" then e = self.npc_list[name]
 	elseif type == "object" then e = self.object_list[name]
 	elseif type == "grid" then e = self.grid_list[name]
+	elseif type == "trap" then e = self.trap_list[name]
 	end
 	if not e then return nil end
 
@@ -303,6 +306,17 @@ function _M:newLevel(level_data, lev, old_lev, game)
 		generator:generate()
 	end
 
+	-- Generate traps
+	if level_data.generator.trap then
+		local generator = require(level_data.generator.trap.class).new(
+			self,
+			map,
+			level,
+			spots
+		)
+		generator:generate()
+	end
+
 	-- Generate actors
 	if level_data.generator.actor then
 		local generator = require(level_data.generator.actor.class).new(
diff --git a/game/engine/class.lua b/game/engine/class.lua
index 90669671680ead676da1a1630a9fd3e49ebe03d7..b83f822eea6afd5edc1323c8b1cf3c45c44ba724 100644
--- a/game/engine/class.lua
+++ b/game/engine/class.lua
@@ -121,7 +121,13 @@ local function serialize_data(outf, name, value, saved, filter, allow, savefile,
 			for k,v in pairs(value) do      -- save its fields
 --				print(allow, k , filter[k])
 				if (not allow and not filter[k]) or (allow and filter[k]) then
-					local fieldname = string.format("%s[%s]", name, basicSerialize(k))
+					local fieldname
+					-- Special case to handle index by objects
+					if type(k) == "table" and k.__CLASSNAME then
+						fieldname = string.format("%s[loadObject('%s')]", name, savefile:getFileName(k))
+					else
+						fieldname = string.format("%s[%s]", name, basicSerialize(k))
+					end
 					serialize_data(outf, fieldname, v, saved, filter, allow, savefile, false)
 				end
 			end
diff --git a/game/engine/generator/trap/Random.lua b/game/engine/generator/trap/Random.lua
new file mode 100644
index 0000000000000000000000000000000000000000..cb3a5d854926d6be55016de15d8e914e602d883f
--- /dev/null
+++ b/game/engine/generator/trap/Random.lua
@@ -0,0 +1,37 @@
+require "engine.class"
+local Map = require "engine.Map"
+require "engine.Generator"
+module(..., package.seeall, class.inherit(engine.Generator))
+
+function _M:init(zone, map, level)
+	engine.Generator.init(self, zone, map)
+	self.level = level
+	local data = level.data.generator.trap
+
+	-- Setup the entities list
+	level:setEntitiesList("trap", zone:computeRarities("trap", zone.trap_list, level, nil))
+
+	self.filters = data.filters
+	self.nb_trap = data.nb_trap or {10, 20}
+	self.level_range = data.level_range or {level, level}
+end
+
+function _M:generate()
+	for i = 1, rng.range(self.nb_trap[1], self.nb_trap[2]) do
+		local f = nil
+		if self.filters then f = self.filters[rng.range(1, #self.filters)] end
+		local o = self.zone:makeEntity(self.level, "trap", f)
+		if o then
+			local x, y = rng.range(0, self.map.w), rng.range(0, self.map.h)
+			local tries = 0
+			while (self.map:checkEntity(x, y, Map.TERRAIN, "block_move") or self.map(x, y, Map.TRAP)) and tries < 100 do
+				x, y = rng.range(0, self.map.w-1), rng.range(0, self.map.h-1)
+				tries = tries + 1
+			end
+			if tries < 100 then
+				self.map(x, y, Map.TRAP, o)
+				o:added()
+			end
+		end
+	end
+end
diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index f8b3f52729be7b1b3a1d81658eeb10f090fa1ce3..8a90fce00cfd461b57202e902a1f90d0e0edae83 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -9,7 +9,8 @@ local Target = require "engine.Target"
 local Level = require "engine.Level"
 local Birther = require "engine.Birther"
 
-local Grid = require "engine.Grid"
+local Trap = require "mod.class.Trap"
+local Grid = require "mod.class.Grid"
 local Actor = require "mod.class.Actor"
 local ActorStats = require "engine.interface.ActorStats"
 local ActorResource = require "engine.interface.ActorResource"
@@ -98,7 +99,7 @@ end
 
 function _M:loaded()
 	engine.GameTurnBased.loaded(self)
-	Zone:setup{npc_class="mod.class.NPC", grid_class="mod.class.Grid", object_class="mod.class.Object"}
+	Zone:setup{npc_class="mod.class.NPC", grid_class="mod.class.Grid", object_class="mod.class.Object", trap_class="mod.class.Trap"}
 	Map:setViewerActor(self.player)
 	Map:setViewPort(200, 20, self.w - 200, math.floor(self.h * 0.80) - 20, 32, 32, nil, 20, true)
 	self.key = engine.KeyBind.new()
@@ -207,7 +208,7 @@ function _M:display()
 	self.hotkeys_display:display():toScreen(self.hotkeys_display.display_x, self.hotkeys_display.display_y)
 
 	-- Now the map, if any
-	if self.level and self.level.map and self.level.map.loaded then
+	if self.level and self.level.map and self.level.map.finished then
 		-- Display the map and compute FOV for the player if needed
 		if self.level.map.changed then
 			self.level.map:fovESP(self.player.x, self.player.y, self.player.esp.range or 10)
@@ -224,7 +225,10 @@ function _M:display()
 					local ok = false
 					if game.player:attr("detect_actor") and game.level.map(lx, ly, game.level.map.ACTOR) then ok = true end
 					if game.player:attr("detect_object") and game.level.map(lx, ly, game.level.map.OBJECT) then ok = true end
---					if game.player:attr("detect_trap") and game.level.map(lx, ly, game.level.map.ACTOR) then ok = true end
+					if game.player:attr("detect_trap") and game.level.map(lx, ly, game.level.map.TRAP) then
+						game.level.map(lx, ly, game.level.map.TRAP):setKnown(self.player, true)
+						ok = true
+					end
 
 					if ok then
 						game.level.map.seens(lx, ly, true)
@@ -241,7 +245,7 @@ function _M:display()
 		-- Display a tooltip if available
 		local mx, my = core.mouse.get()
 		local tmx, tmy = self.level.map:getMouseTile(mx, my)
-		local tt = self.level.map:checkEntity(tmx, tmy, Map.ACTOR, "tooltip") or self.level.map:checkEntity(tmx, tmy, Map.OBJECT, "tooltip") or self.level.map:checkEntity(tmx, tmy, Map.TERRAIN, "tooltip")
+		local tt = self.level.map:checkEntity(tmx, tmy, Map.ACTOR, "tooltip") or self.level.map:checkEntity(tmx, tmy, Map.OBJECT, "tooltip") or self.level.map:checkEntity(tmx, tmy, Map.TRAP, "tooltip") or self.level.map:checkEntity(tmx, tmy, Map.TERRAIN, "tooltip")
 		if tt and self.level.map.seens(tmx, tmy) then
 			self.tooltip:set("%s", tt)
 			local t = self.tooltip:display()
diff --git a/game/modules/tome/class/Trap.lua b/game/modules/tome/class/Trap.lua
new file mode 100644
index 0000000000000000000000000000000000000000..3aa8e02c772f000f740fb39e314a7f5193ccfe17
--- /dev/null
+++ b/game/modules/tome/class/Trap.lua
@@ -0,0 +1,15 @@
+require "engine.class"
+require "engine.Trap"
+
+module(..., package.seeall, class.inherit(
+	engine.Trap
+))
+
+function _M:init(t, no_default)
+	engine.Trap.init(self, t, no_default)
+end
+
+--- Returns a tooltip for the trap
+function _M:tooltip()
+	return self.name
+end
diff --git a/game/modules/tome/data/birth/mage.lua b/game/modules/tome/data/birth/mage.lua
index 4912e99e3d086a309510d19fb5ae2f57fd89ae6b..fe4fab3e0f68f1a22219e6cd9147276c60894922 100644
--- a/game/modules/tome/data/birth/mage.lua
+++ b/game/modules/tome/data/birth/mage.lua
@@ -70,6 +70,7 @@ newBirthDescriptor{
 		[ActorTalents.T_MANATHRUST] = 1,
 		[ActorTalents.T_FLAME] = 1,
 		[ActorTalents.T_FREEZE] = 1,
+		[ActorTalents.T_SENSE] = 5,
 	},
 }
 
diff --git a/game/modules/tome/data/general/npcs/skeleton.lua b/game/modules/tome/data/general/npcs/skeleton.lua
index 9ec13fe67ab2c17def15e0673eb5492ad61cf4bc..7bee1d9d9831c1107fe8621411a599f9b3afd873 100644
--- a/game/modules/tome/data/general/npcs/skeleton.lua
+++ b/game/modules/tome/data/general/npcs/skeleton.lua
@@ -29,7 +29,6 @@ newEntity{ base = "BASE_NPC_SKELETON",
 	rarity = 4,
 	max_life = resolvers.rngavg(40,50),
 	combat_armor = 5, combat_def = 1,
-	talents = resolvers.talents{ [Talents.T_SUMMON]=1 },
 }
 
 newEntity{ base = "BASE_NPC_SKELETON",
diff --git a/game/modules/tome/data/general/objects/scrolls.lua b/game/modules/tome/data/general/objects/scrolls.lua
index cc86decc7d03aaefa1860852cfd1988c6a378215..952bb4f614dac9d2614b60affa0b5d7310094302 100644
--- a/game/modules/tome/data/general/objects/scrolls.lua
+++ b/game/modules/tome/data/general/objects/scrolls.lua
@@ -109,7 +109,11 @@ newEntity{ base = "BASE_SCROLL",
 	cost = 5,
 
 	use_simple = { name="detect enemies within a certain range", use = function(self, who)
-		who:detect(game.level.map.ACTOR, 20)
+		local rad = 15 + self:getMag(20)
+		self:setEffect(self.EFF_SENSE, 2, {
+			range = rad,
+			actor = 1,
+		})
 		game.logSeen(who, "%s reads a %s!", who.name:capitalize(), self:getName())
 		return "destroy", true
 	end}
diff --git a/game/modules/tome/data/talents/spells/arcane.lua b/game/modules/tome/data/talents/spells/arcane.lua
index d7e29134d7c0ca960afe92b0d7d75115f9572c99..056aa23cba27d0542f7c6b086f9de9dd8431e9c1 100644
--- a/game/modules/tome/data/talents/spells/arcane.lua
+++ b/game/modules/tome/data/talents/spells/arcane.lua
@@ -59,7 +59,7 @@ newTalent{
 		self.combat_spellpower = self.combat_spellpower - 5
 	end,
 	info = function(self, t)
-		return [[Your mastery of magic allows your to permanently increase your spellpower by 5.]]
+		return ([[Your mastery of magic allows your to permanently increase your spellpower by %d.]]):format(5 * self:getTalentLevelRaw(t))
 	end,
 }
 
diff --git a/game/modules/tome/data/zones/tower-amon-sul/traps.lua b/game/modules/tome/data/zones/tower-amon-sul/traps.lua
new file mode 100644
index 0000000000000000000000000000000000000000..f281ce45e8b2ece102c8ffc92cbed81c1ca68c64
--- /dev/null
+++ b/game/modules/tome/data/zones/tower-amon-sul/traps.lua
@@ -0,0 +1 @@
+load("/data/general/traps/basic.lua")
diff --git a/game/modules/tome/data/zones/tower-amon-sul/zone.lua b/game/modules/tome/data/zones/tower-amon-sul/zone.lua
index 5e09967d4febc4bb7c846d160aa1a9ef2979390b..2ca9c1006d6e188b65039d9fe7390f635d44434b 100644
--- a/game/modules/tome/data/zones/tower-amon-sul/zone.lua
+++ b/game/modules/tome/data/zones/tower-amon-sul/zone.lua
@@ -30,6 +30,10 @@ return {
 			nb_object = {6, 9},
 			filters = { {type="potion" }, {type="potion" }, {type="potion" }, {type="scroll" }, {}, {} }
 		},
+		trap = {
+			class = "engine.generator.trap.Random",
+			nb_trap = {60, 90},
+		},
 	},
 	levels =
 	{
diff --git a/src/map.c b/src/map.c
index 7f04b5e1c38ccca4f317a40531748b3ed855c5ae..7d56dc7ecbc5a4a6c354c9cc7606424ccf214d14 100644
--- a/src/map.c
+++ b/src/map.c
@@ -34,6 +34,7 @@ static int map_new(lua_State *L)
 	map->mheight = mheight;
 	map->grids_terrain = calloc(w, sizeof(GLuint*));
 	map->grids_actor = calloc(w, sizeof(GLuint*));
+	map->grids_trap = calloc(w, sizeof(GLuint*));
 	map->grids_object = calloc(w, sizeof(GLuint*));
 	map->grids_seens = calloc(w, sizeof(bool*));
 	map->grids_remembers = calloc(w, sizeof(bool*));
@@ -46,6 +47,7 @@ static int map_new(lua_State *L)
 		map->grids_terrain[i] = calloc(h, sizeof(GLuint));
 		map->grids_actor[i] = calloc(h, sizeof(GLuint));
 		map->grids_object[i] = calloc(h, sizeof(GLuint));
+		map->grids_trap[i] = calloc(h, sizeof(GLuint));
 		map->grids_seens[i] = calloc(h, sizeof(bool));
 		map->grids_remembers[i] = calloc(h, sizeof(bool));
 		map->grids_lites[i] = calloc(h, sizeof(bool));
@@ -77,6 +79,7 @@ static int map_free(lua_State *L)
 	{
 		free(map->grids_terrain[i]);
 		free(map->grids_actor[i]);
+		free(map->grids_trap[i]);
 		free(map->grids_object[i]);
 		free(map->grids_seens[i]);
 		free(map->grids_remembers[i]);
@@ -85,6 +88,7 @@ static int map_free(lua_State *L)
 	free(map->grids_terrain);
 	free(map->grids_actor);
 	free(map->grids_object);
+	free(map->grids_trap);
 	free(map->grids_seens);
 	free(map->grids_remembers);
 	free(map->grids_lites);
@@ -98,13 +102,16 @@ static int map_set_grid(lua_State *L)
 	map_type *map = (map_type*)auxiliar_checkclass(L, "core{map}", 1);
 	int x = luaL_checknumber(L, 2);
 	int y = luaL_checknumber(L, 3);
-	GLuint *t = lua_isnil(L, 4) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 4);
-	GLuint *o = lua_isnil(L, 5) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 5);
-	GLuint *a = lua_isnil(L, 6) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 6);
+	GLuint *g = lua_isnil(L, 4) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 4);
+	GLuint *t = lua_isnil(L, 5) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 5);
+	GLuint *o = lua_isnil(L, 6) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 6);
+	GLuint *a = lua_isnil(L, 7) ? NULL : (GLuint*)auxiliar_checkclass(L, "gl{texture}", 7);
 
-	map->grids_terrain[x][y] = t ? *t : 0;
+	map->grids_terrain[x][y] = g ? *g : 0;
+	map->grids_trap[x][y] = t ? *t : 0;
 	map->grids_actor[x][y] = a ? *a : 0;
 	map->grids_object[x][y] = o ? *o : 0;
+	return 0;
 }
 
 static int map_set_seen(lua_State *L)
@@ -218,6 +225,16 @@ static int map_to_screen(lua_State *L)
 							glTexCoord2f(0,1); glVertex3f(0  +dx, map->tile_h +dy,-99);
 							glEnd();
 						}
+						if (map->grids_trap[i][j])
+						{
+							glBindTexture(GL_TEXTURE_2D, map->grids_trap[i][j]);
+							glBegin(GL_QUADS);
+							glTexCoord2f(0,0); glVertex3f(0  +dx, 0  +dy,-99);
+							glTexCoord2f(1,0); glVertex3f(map->tile_w +dx, 0  +dy,-99);
+							glTexCoord2f(1,1); glVertex3f(map->tile_w +dx, map->tile_h +dy,-99);
+							glTexCoord2f(0,1); glVertex3f(0  +dx, map->tile_h +dy,-99);
+							glEnd();
+						}
 						if (map->grids_object[i][j])
 						{
 							glBindTexture(GL_TEXTURE_2D, map->grids_object[i][j]);
@@ -261,6 +278,16 @@ static int map_to_screen(lua_State *L)
 							glTexCoord2f(0,1); glVertex3f(0  +dx, map->tile_h +dy,-99);
 							glEnd();
 						}
+						else if (map->grids_trap[i][j])
+						{
+							glBindTexture(GL_TEXTURE_2D, map->grids_trap[i][j]);
+							glBegin(GL_QUADS);
+							glTexCoord2f(0,0); glVertex3f(0  +dx, 0  +dy,-99);
+							glTexCoord2f(1,0); glVertex3f(map->tile_w +dx, 0  +dy,-99);
+							glTexCoord2f(1,1); glVertex3f(map->tile_w +dx, map->tile_h +dy,-99);
+							glTexCoord2f(0,1); glVertex3f(0  +dx, map->tile_h +dy,-99);
+							glEnd();
+						}
 						else if (map->grids_terrain[i][j])
 						{
 							glBindTexture(GL_TEXTURE_2D, map->grids_terrain[i][j]);
diff --git a/src/map.h b/src/map.h
index dea02c87f262bc881a01ab9418826d7da607a855..46fdbd27b6e8dc50aae2b017dc65ce04657d8238 100644
--- a/src/map.h
+++ b/src/map.h
@@ -7,6 +7,7 @@ typedef struct {
 	GLuint **grids_terrain;
 	GLuint **grids_actor;
 	GLuint **grids_object;
+	GLuint **grids_trap;
 	bool **grids_seens;
 	bool **grids_remembers;
 	bool **grids_lites;