diff --git a/game/engines/default/engine/generator/map/MapScript.lua b/game/engines/default/engine/generator/map/MapScript.lua
index 4e34a11fbcb080e2b1fc3d07294fbe74a63cd3f5..61894cbf5d638c431af671a58852035b96a2074c 100644
--- a/game/engines/default/engine/generator/map/MapScript.lua
+++ b/game/engines/default/engine/generator/map/MapScript.lua
@@ -42,7 +42,15 @@ end
 function _M:resolve(c, list, force)
 	if force then return Generator.resolve(self, c, list, force) end
 	if self.self_tiles[c] then
-		return Generator.resolve(self, self.self_tiles[c].grid or '.', list, true)
+		if type(self.self_tiles[c].grid) == "table" and self.self_tiles[c].grid.__ATOMIC then
+			local res = self.self_tiles[c].grid
+			if res.force_clone then res = res:clone() end
+			res:resolve()
+			res:resolve(nil, true)
+			return res
+		else
+			return Generator.resolve(self, self.self_tiles[c].grid or '.', list, true)
+		end
 	else
 		return Generator.resolve(self, c, list, force)
 	end
diff --git a/game/modules/tome/class/GameState.lua b/game/modules/tome/class/GameState.lua
index 42bf4b6b31452a2323941bb04bcbd796c6294c73..1fe2aacc195f0ab711815eb2ace5251736e5a3df 100644
--- a/game/modules/tome/class/GameState.lua
+++ b/game/modules/tome/class/GameState.lua
@@ -3123,11 +3123,15 @@ function _M:dynamicZoneEntry(g, id, zone_def, zone_lists, zone_alter)
 		def.__embed_lists_def = self.dynamic_zone.lists
 		if self.dynamic_zone.alter then
 			def.__alter_back_def = {short_name=game.zone.short_name, name=game.zone.name}
-			def.__alter_back_fct = function(backdef, name, base_terrain)
-				base_terrain.change_level_shift_back = true
-				base_terrain.change_zone_auto_stairs = true
-				base_terrain.name = name:format(backdef.name)
-				base_terrain.change_zone = backdef.short_name
+			def.__alter_back_fct = function(zone, backdef, name, base_terrain)
+				local terrain = base_terrain:cloneFull()
+				terrain.change_level_shift_back = true
+				terrain.change_zone_auto_stairs = true
+				terrain.name = name:format(backdef.name)
+				terrain.change_zone = backdef.short_name
+				terrain.define_as = "DYNAMIC_ZONE_EXIT"
+				terrain:altered()
+				zone.grid_list.DYNAMIC_ZONE_EXIT = terrain
 			end
 			def.__alter_back_custom = self.dynamic_zone.alter
 		end
@@ -3153,7 +3157,7 @@ function _M:dynamicZoneEntry(g, id, zone_def, zone_lists, zone_alter)
 
 			-- Alter whatever we need. Most likely the exit, so we provide an easy function for that
 			if zone.__alter_back_fct then
-				zone.__alter_back_custom(zone, function(name, base_terrain) zone.__alter_back_fct(zone.__alter_back_def, name, base_terrain) end)
+				zone.__alter_back_custom(zone, function(name, base_terrain) zone:__alter_back_fct(zone.__alter_back_def, name, base_terrain) end)
 			end
 		end
 		return mod.class.Zone.new(self.dynamic_zone.id, def)
diff --git a/game/modules/tome/class/NicerTiles.lua b/game/modules/tome/class/NicerTiles.lua
index 9ca65267fa22161a2c004ae67f8b5ba2e2e0e5ae..04d621b7e177d1b3f26c0ae789e0f494c2ccd6c6 100644
--- a/game/modules/tome/class/NicerTiles.lua
+++ b/game/modules/tome/class/NicerTiles.lua
@@ -1221,6 +1221,30 @@ grass_wm = { method="borders", type="grass", forbid={lava=true, rock=true},
 	default7i={add_mos={{image="terrain/grass_worldmap/grass_inner_7_%02d.png", display_x=-1, display_y=-1}}, min=1, max=2},
 	default9i={add_mos={{image="terrain/grass_worldmap/grass_inner_9_%02d.png", display_x=1, display_y=-1}}, min=1, max=2},
 },
+psitechwall = { method="walls", type="psitechwall", forbid={}, use_type=true, extended=true, consider_diagonal_doors=true,
+	default8={add_displays={{image="terrain/psicave/psitechwall_8_%d.png", display_y=-1, z=16}}, min=1, max=1},
+	default8p={add_displays={{image="terrain/psicave/psitech_V3_pillar_top_0%d.png", display_y=-1, z=16}}, min=1, max=1},
+	default7={add_displays={{image="terrain/psicave/psitech_V3_inner_7_01.png", display_y=-1, z=16}}, min=1, max=1},
+	default9={add_displays={{image="terrain/psicave/psitech_V3_inner_9_01.png", display_y=-1, z=16}}, min=1, max=1},
+	default7i={add_displays={{image="terrain/psicave/psitech_V3_3_01.png", display_y=-1, z=16}}, min=1, max=1},
+	default8i={add_displays={{image="terrain/psicave/psitechwall_8h_1.png", display_y=-1, z=16}}, min=1, max=1},
+	default9i={add_displays={{image="terrain/psicave/psitech_V3_1_01.png", display_y=-1, z=16}}, min=1, max=1},
+	default73i={add_displays={{image="terrain/psicave/psitechwall_91d_1.png", display_y=-1, z=16}}, min=1, max=1},
+	default91i={add_displays={{image="terrain/psicave/psitechwall_73d_1.png", display_y=-1, z=16}}, min=1, max=1},
+
+	default2={image="terrain/psicave/psitech_floor_1_01.png", add_mos={{image="terrain/psicave/psitech_V3_8_0%d.png"}}, min=1, max=3},
+	default2p={image="terrain/psicave/psitech_floor_1_01.png", add_mos={{image="terrain/psicave/psitech_V3_pillar_bottom_0%d.png"}}, min=1, max=3},
+	default1={image="terrain/psicave/psitech_floor_1_01.png", add_mos={{image="terrain/psicave/psitech_V3_inner_1_01.png"}}, min=1, max=1},
+	default3={image="terrain/psicave/psitech_floor_1_01.png", add_mos={{image="terrain/psicave/psitech_V3_inner_3_01.png"}}, min=1, max=1},
+	default1i={image="terrain/psicave/psitech_floor_1_01.png", add_mos={{image="terrain/psicave/psitech_V3_7_01.png"}}, min=1, max=1},
+	default2i={image="terrain/psicave/psitech_floor_1_01.png", add_mos={{image="terrain/psicave/psitechwall_2h_1.png"}}, min=1, max=1},
+	default3i={image="terrain/psicave/psitech_floor_1_01.png", add_mos={{image="terrain/psicave/psitech_V3_9_01.png"}}, min=1, max=1},
+	default19i={image="terrain/psicave/psitech_floor_1_01.png", add_mos={{image="terrain/psicave/psitechwall_19d_1.png"}}, min=1, max=1},
+	default37i={image="terrain/psicave/psitech_floor_1_01.png", add_mos={{image="terrain/psicave/psitechwall_37d_1.png"}}, min=1, max=1},
+
+	default4={add_displays={{image="terrain/psicave/psitech_ver_edge_left_01.png", display_x=-1}}, min=1, max=1},
+	default6={add_displays={{image="terrain/psicave/psitech_ver_edge_right_01.png", display_x=1}}, min=1, max=1},
+},
 }
 _M.generic_borders_defs = defs
 
diff --git a/game/modules/tome/data/general/events/drake-cave.lua b/game/modules/tome/data/general/events/drake-cave.lua
index fead4b07b6a3558c2912f0ee1dabff13de4108bc..3a9d924873a1466567b75e0c39c8a7015f2803a4 100644
--- a/game/modules/tome/data/general/events/drake-cave.lua
+++ b/game/modules/tome/data/general/events/drake-cave.lua
@@ -47,7 +47,7 @@ local g = game.state:dynamicZoneEntry(game.level.map(x, y, engine.Map.TERRAIN):c
 			min_floor = 1200,
 			floor = "CAVEFLOOR",
 			wall = "CAVEWALL",
-			up = "CAVE_LADDER_UP_WILDERNESS",
+			up = "DYNAMIC_ZONE_EXIT",
 			door = "CAVEFLOOR",
 		},
 		actor = {
diff --git a/game/modules/tome/data/general/grids/psicave.lua b/game/modules/tome/data/general/grids/psicave.lua
new file mode 100644
index 0000000000000000000000000000000000000000..33ab12ae327a66df8779e11b35ff4eb468027c8c
--- /dev/null
+++ b/game/modules/tome/data/general/grids/psicave.lua
@@ -0,0 +1,109 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009 - 2019 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 psitech_wall_editer = { method="sandWalls_def", def="psitechwall"}
+
+newEntity{
+	define_as = "PSYCAVEFLOOR",
+	type = "floor", subtype = "psitech",
+	name = "psitech floor", image = "terrain/psicave/psitech_floor_1_01.png",
+	display = '.', color=colors.SANDY_BROWN, back_color=colors.DARK_UMBER,
+	grow = "PSYCAVEWALL",
+	nice_tiler = { method="replace", base={"PSYCAVEFLOOR", 100, 1, 5}},
+}
+for i = 1, 5 do newEntity{ base = "PSYCAVEFLOOR", define_as = "PSYCAVEFLOOR"..i, image = "terrain/psicave/psitech_floor_"..i.."_01.png"} end
+
+newEntity{
+	define_as = "PSYCAVEWALL",
+	type = "wall", subtype = "psitech",
+	name = "psitech walls", image = "terrain/psicave/psitechwall_5_1.png",
+	display = '#', color={r=203,g=189,b=72}, back_color={r=93,g=79,b=22},
+	always_remember = true,
+	can_pass = {pass_wall=1},
+	does_block_move = true,
+	block_sight = true,
+	air_level = -10,
+	dig = "PSYCAVEFLOOR",
+	nice_editer = psitech_wall_editer,
+	nice_tiler = { method="replace", base={"PSYCAVEWALL", 100, 1, 9}},
+}
+for i = 1, 9 do newEntity{ base = "PSYCAVEWALL", define_as = "PSYCAVEWALL"..i, image = "terrain/psicave/psitechwall_5_"..i..".png"} end
+
+-----------------------------------------
+-- Doors
+-----------------------------------------
+newEntity{
+	define_as = "PSYCAVE_DOOR",
+	type = "wall", subtype = "psitech",
+	name = "psitech door", image = "terrain/psicave/psitech_door1.png",
+	display = '+', color={r=203,g=189,b=72}, back_color={r=93,g=79,b=22},
+	nice_tiler = { method="door3d", north_south="PSYCAVE_DOOR_VERT", west_east="PSYCAVE_DOOR_HORIZ" },
+	door_sound = "ambient/door_creaks/icedoor-break",
+	notice = true,
+	always_remember = true,
+	block_sight = true,
+	is_door = true,
+	door_opened = "PSYCAVE_DOOR_OPEN",
+	dig = "FLOOR",
+}
+newEntity{
+	define_as = "PSYCAVE_DOOR_OPEN",
+	type = "wall", subtype = "psitech",
+	name = "psitech door (open)", image="terrain/psicave/psitech_door1_open.png",
+	display = "'", color_r=238, color_g=154, color_b=77, back_color=colors.DARK_GREY,
+	always_remember = true,
+	is_door = true,
+	door_closed = "PSYCAVE_DOOR",
+}
+newEntity{ base = "PSYCAVE_DOOR", define_as = "PSYCAVE_DOOR_HORIZ", z=3, image = "terrain/psicave/psitech_door1.png", add_displays = {class.new{image="terrain/psicave/psitechwall_8_1.png", z=18, display_y=-1}}, door_opened = "PSYCAVE_DOOR_HORIZ_OPEN"}
+newEntity{ base = "PSYCAVE_DOOR_OPEN", define_as = "PSYCAVE_DOOR_HORIZ_OPEN", image = "terrain/psicave/psitech_floor_1_01.png", add_mos={{image="terrain/psicave/psitech_door1_open_backg.png"}}, add_displays = {class.new{image="terrain/psicave/psitech_door1_open.png", z=17}, class.new{image="terrain/psicave/psitechwall_8_1.png", z=18, display_y=-1}}, door_closed = "PSYCAVE_DOOR_HORIZ"}
+newEntity{ base = "PSYCAVE_DOOR", define_as = "PSYCAVE_DOOR_VERT", image = "terrain/psicave/psitech_floor_1_01.png", add_displays = {class.new{image="terrain/psicave/psitech_door1_vert.png", z=17}, class.new{image="terrain/psicave/psitech_door1_vert_north.png", z=18, display_y=-1}}, door_opened = "PSYCAVE_DOOR_OPEN_VERT", dig = "PSYCAVE_DOOR_OPEN_VERT"}
+newEntity{ base = "PSYCAVE_DOOR_OPEN", define_as = "PSYCAVE_DOOR_OPEN_VERT", z=3, image = "terrain/psicave/psitech_floor_1_01.png", add_mos={{image="terrain/psicave/psitech_door1_open_vert_backg.png"}}, add_displays = {class.new{image="terrain/psicave/psitech_door1_open_vert.png", z=17, add_mos={{image="terrain/psicave/psitech_door1_open_vert_north_backg.png", display_y=-1}}}, class.new{image="terrain/psicave/psitech_door1_open_vert_north.png", z=18, display_y=-1}}, door_closed = "PSYCAVE_DOOR_VERT"}
+
+-----------------------------------------
+-- Cavy exits
+-----------------------------------------
+
+newEntity{
+	define_as = "PSYCAVE_LADDER_DOWN",
+	type = "floor", subtype = "psitech",
+	name = "ladder to the next level", image = "terrain/psicave/psitech_floor_1_01.png", add_displays = {class.new{image="terrain/psicave/psitech_stairs_down_1_01.png"}},
+	display = '>', color_r=255, color_g=255, color_b=0,
+	notice = true,
+	always_remember = true,
+	change_level = 1,
+}
+newEntity{
+	define_as = "PSYCAVE_LADDER_UP",
+	type = "floor", subtype = "psitech",
+	name = "ladder to the previous level", image = "terrain/psicave/psitech_floor_1_01.png", add_displays = {class.new{image="terrain/psicave/psitech_stairs_up_1_01.png"}},
+	display = '<', color_r=255, color_g=255, color_b=0,
+	notice = true,
+	always_remember = true,
+	change_level = -1,
+}
+newEntity{
+	define_as = "PSYCAVE_LADDER_UP_WILDERNESS",
+	type = "floor", subtype = "psitech",
+	name = "ladder to worldmap", image = "terrain/psicave/psitech_floor_1_01.png", add_displays = {class.new{image="terrain/psicave/psitech_stairs_exit_1_01.png"}},
+	display = '<', color_r=255, color_g=255, color_b=0,
+	notice = true,
+	change_level = 1,
+	change_zone = "wilderness",
+}
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_1_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_1_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..daf7a319abc7cf13621992e1872abb6677289656
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_1_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_3_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_3_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..e11183bf96ce50b4dc9fc63781a24c353dee7a90
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_3_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_7_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_7_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..f76c30d3a781c072dc75d2f8d164597d59559588
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_7_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b57d0c2d3eb6865d3e2aa054bcdf303e394f01a
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_02.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_02.png
new file mode 100644
index 0000000000000000000000000000000000000000..f6b1a2f95eaec03065aefde97999cce6724f2d0d
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_02.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_03.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_03.png
new file mode 100644
index 0000000000000000000000000000000000000000..7c2b5ee1302f5ab868038a18b7e8ee1081e01a64
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_03.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_04.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_04.png
new file mode 100644
index 0000000000000000000000000000000000000000..e65482d0ccda0f496c773078ae03a0f7c838743b
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_04.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_05.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_05.png
new file mode 100644
index 0000000000000000000000000000000000000000..44bb192ceee7cf0b57ef57788b538e3f25f383a9
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_8_05.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_9_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_9_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..367d9412b4d1d22154548b184e0ecaeb90ddc5fb
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_9_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_inner_1_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_inner_1_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..bf03153d8b3bfbf2ec2e13e989b443d1c0440388
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_inner_1_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_inner_3_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_inner_3_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..d5625d7fe291658a3d8bd8aad78511f3750fbc34
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_inner_3_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_inner_7_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_inner_7_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..baf0e3308ba166bf55b3b7ce6f3d93fbc8ac22d9
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_inner_7_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_inner_9_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_inner_9_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..88fbfe769f033b565e2a58f18ef4a1fead789a2a
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_inner_9_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_pillar_bottom_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_pillar_bottom_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..cfa06d2c9476167de62c39ddabac077ab4914be2
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_pillar_bottom_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_pillar_bottom_02.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_pillar_bottom_02.png
new file mode 100644
index 0000000000000000000000000000000000000000..fe66ce42a7fe72f053ca0838bcbf997e924f3d56
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_pillar_bottom_02.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_pillar_top_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_pillar_top_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..11fa8ff5d6cc47c9bd29d4354dc09551d75b347b
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_V3_pillar_top_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1.png
new file mode 100644
index 0000000000000000000000000000000000000000..e68d2491a20cf5c2f4ed25581a581b7fd87575ef
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_open.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_open.png
new file mode 100644
index 0000000000000000000000000000000000000000..f329976867fc7c7e653ccb8e0061e46886a25295
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_open.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_open_vert.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_open_vert.png
new file mode 100644
index 0000000000000000000000000000000000000000..55b8f1c7f7322b960031160c4f7d34c5b750133c
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_open_vert.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_open_vert_north.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_open_vert_north.png
new file mode 100644
index 0000000000000000000000000000000000000000..d301e3b5167d8398db1607e069db9ec41cafdbf8
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_open_vert_north.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_vert.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_vert.png
new file mode 100644
index 0000000000000000000000000000000000000000..204e5d9b74db343b5684766f16db42870b9e914a
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_vert.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_vert_north.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_vert_north.png
new file mode 100644
index 0000000000000000000000000000000000000000..f499adf3292e20201d29733b5b59e1351df303d1
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_door1_vert_north.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_1_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_1_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..3c1d493e16b972ff78c82a419f1c13e933dc8cac
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_1_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_2_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_2_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..d7c9b3f18ad4ae7983d077e26860b181b3b466af
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_2_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_3_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_3_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..64896f8113f7466ebb8e65c697741e05798d1b27
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_3_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_4_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_4_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..3cbf93c9fe58a638ab1f9740757e406a4c59d71d
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_4_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_5_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_5_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..6ccf1a15503700093226a8b6e72ca562ff5fd0ac
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_floor_5_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_stairs_down_1_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_stairs_down_1_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..14da32ade5036f0ea1d193851f997caa6e350429
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_stairs_down_1_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_stairs_exit_1_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_stairs_exit_1_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..ea0fe480282da6fa5d42278c9e8674ea2e03f8eb
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_stairs_exit_1_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_stairs_up_1_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_stairs_up_1_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..09a57ed1a51b56b7099bda11b9c0cc88adff6290
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_stairs_up_1_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_ver_edge_left_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_ver_edge_left_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..531d46c8a4985af5919c2cfce4712af0a0f778d1
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_ver_edge_left_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_ver_edge_right_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_ver_edge_right_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..4960781b74e86c7d507530c93e5a23301bcbe52d
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitech_ver_edge_right_01.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_19d_1.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_19d_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..22c873310e9bfc882b5361f78e5311a5a16653f3
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_19d_1.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_2h_1.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_2h_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..317170c35a27d0bd272911c6304d2de3301e559b
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_2h_1.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_37d_1.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_37d_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..61025bafb239ef237f0b0727086bb2352138393a
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_37d_1.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_1.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..85c1f763533f28c5640e561dca654f2fbd9667b2
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_1.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_2.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..75dce977a8f61a3242acfa124db7edad73cdec59
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_2.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_3.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_3.png
new file mode 100644
index 0000000000000000000000000000000000000000..0b52b97c4af6776c83b4344efaafe428d728caf4
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_3.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_4.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_4.png
new file mode 100644
index 0000000000000000000000000000000000000000..0c0a65fba6aec1cffd71e6c8797774ed317dd68a
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_4.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_5.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_5.png
new file mode 100644
index 0000000000000000000000000000000000000000..e6ae3cbb9c7ea68dbf41ab3fc705226e51793f4a
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_5.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_6.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_6.png
new file mode 100644
index 0000000000000000000000000000000000000000..90c6c71630fee8bbfdeed097bd83c21c49c3361f
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_6.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_7.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_7.png
new file mode 100644
index 0000000000000000000000000000000000000000..3fa8a2467f60372a0fd787f036ce8d9e0e7f9b57
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_7.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_8.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_8.png
new file mode 100644
index 0000000000000000000000000000000000000000..4a50345a7e3822e5b81764fbb87e5d6fdfd3ec7d
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_8.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_9.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_9.png
new file mode 100644
index 0000000000000000000000000000000000000000..56a1ded26a50739cfba1034a68f81b6d03b3e9a1
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_5_9.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_73d_1.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_73d_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..7209d94c57c8285fe4eede028ae91af29d702238
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_73d_1.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_8_1.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_8_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..5c0c964ff3ecc5aa04c3998c065c2c10f0a28670
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_8_1.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_8h_1.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_8h_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..d7c10e6f344d0e465b982b03853fc60f53b67dd5
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_8h_1.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_91d_1.png b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_91d_1.png
new file mode 100644
index 0000000000000000000000000000000000000000..c2a8600432122a8b9eb89382643f8f6b75db536c
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/psicave/psitechwall_91d_1.png differ
diff --git a/game/modules/tome/data/maps/zones/collapsed-tower.lua b/game/modules/tome/data/maps/zones/collapsed-tower.lua
index 3c1583972a7870a84c1e0c9c3db15ab9ad007501..0a0ba58f5549579ebe856962663147fe917b408e 100644
--- a/game/modules/tome/data/maps/zones/collapsed-tower.lua
+++ b/game/modules/tome/data/maps/zones/collapsed-tower.lua
@@ -75,7 +75,7 @@ defineTile('.', "FLOOR")
 defineTile('#', "HARDWALL")
 defineTile('+', "DOOR")
 defineTile('!', "DOOR_VAULT")
-defineTile('>', "DOWN")
+defineTile('>', "DYNAMIC_ZONE_EXIT")
 
 
 defineTile('b', "FLOOR", {random_filter={add_levels=10, tome_mod="gvault"}}, {random_filter={add_levels=5, name="skeleton magus"}})
diff --git a/game/modules/tome/data/mapscripts/lib/subvault.lua b/game/modules/tome/data/mapscripts/lib/subvault.lua
new file mode 100644
index 0000000000000000000000000000000000000000..31926f80d9451c681fe4f9e3125610b571fc3605
--- /dev/null
+++ b/game/modules/tome/data/mapscripts/lib/subvault.lua
@@ -0,0 +1,110 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009 - 2019 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 map = args.map
+local spot = args.spot
+local char = args.char or '_HV_'..core.game.getTime()
+
+local walltype = args.walltype or "HARDWALL"
+local greater_vaults_list = args.greater_vaults_list
+
+local basemap = table.clone(args.basemap or level.data.generator.map, true)
+basemap.zoneclass = nil
+basemap.rooms = nil
+basemap.required_rooms = nil
+
+local terrains = mod.class.Grid:loadList("/data/general/grids/basic.lua")
+local g = game.state:dynamicZoneEntry(terrains.DOWN, "sub-vault", {
+	name = ("Hidden Vault - %s"):format(zone.name),
+	level_range = {zone:level_adjust_level(level, zone, "actor"), zone:level_adjust_level(level, zone, "actor")},
+	level_scheme = "player",
+	max_level = 1,
+	__applied_difficulty = true, --Difficulty already applied to parent zone
+	actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end,
+	width = 50, height = 50,
+	ambient_music = zone.ambient_music,
+	persistent = "zone",
+	min_material_level = util.getval(zone.min_material_level),
+	max_material_level = util.getval(zone.max_material_level),
+	no_worldport = zone.no_worldport,
+	generator =  {
+		map = table.merge(basemap, {
+			class = "mod.class.generator.map.VaultLevel",
+			subvault_wall = walltype,
+			subvault_up = "DYNAMIC_ZONE_EXIT",
+			greater_vaults_list = greater_vaults_list or nil,
+			entry_path_length = 10, -- path from level entrance to vault (affects space to fight when opening the vault)
+		}),
+		actor = {
+			class = "mod.class.generator.actor.Random",
+			nb_npc = {0, 0},
+		},
+		object = {
+			class = "engine.generator.object.Random",
+			nb_object = {0, 0},
+		},
+		trap = {
+			class = "engine.generator.trap.Random",
+			nb_trap = {0, 0},
+		},
+	},
+	post_process = function(level)
+		for uid, e in pairs(level.entities) do e.faction = e.hard_faction or "enemies" end
+	end,
+}, {
+	npc_list = args.npc_list or {"/data/general/npcs/all.lua"},
+	object_list = args.object_list or {"/data/general/objects/objects.lua"},
+	grid_list = args.grid_list or {"/data/general/grids/basic.lua", "/data/general/grids/water.lua", "/data/general/grids/lava.lua"},
+	trap_list = args.trap_list or {"/data/general/traps/complex.lua", "/data/general/traps/annoy.lua", "/data/general/traps/alarm.lua"},
+},
+function(zone, goback)
+	goback("stairs back to %s", zone.grid_list.UP)
+end)
+
+g.name = "hidden vault"
+g.always_remember = true
+g.desc = [[Crumbling stairs lead down to something.]]
+g.show_tooltip = true
+g.color_r=0 g.color_g=0 g.color_b=255 g.notice = true
+g.special_minimap = colors.VIOLET
+g._use_count = rng.range(2, 4)
+g:altered()
+g:initGlow()
+g.change_level_check = function(self) -- limit stair scumming
+	self._use_count = self._use_count - 1
+	self.name = "collapsing hidden vault"
+	if self._use_count < 1 then
+		self.change_level_check = nil
+		self.change_level = nil
+		self.name = "collapsed hidden vault"
+		self.desc = [[It is fully collapsed, no way down.]]
+		game.log("#VIOLET# The stairway is about to collapses completely, you may still go back but it will be the last time!")
+	elseif self._use_count < 2 then
+		self.name = "nearly collapsed hidden vault"
+		game.log("#VIOLET# The decrepit stairs crumble some more as you climb them.")
+	end
+	game:changeLevel(1, self:real_change(), {temporary_zone_shift=true, direct_switch=true})
+	return true
+end
+game.zone:addEntity(game.level, g, "terrain", x, y)
+
+self:defineTile(char, g)
+if spot then map:put(spot, char) end
+
+return g
diff --git a/game/modules/tome/data/zones/test/mapscripts/rooms_test.lua b/game/modules/tome/data/zones/test/mapscripts/rooms_test.lua
index 83a03f4c04e4e398c6c9e53e452eadc0cb514d82..8fe31232c2190ad407922370047a88624a1fa72a 100644
--- a/game/modules/tome/data/zones/test/mapscripts/rooms_test.lua
+++ b/game/modules/tome/data/zones/test/mapscripts/rooms_test.lua
@@ -23,15 +23,17 @@ local tm = Tilemap.new(self.mapsize, '#')
 
 -- self.data.greater_vaults_list = {"32-chambers"}
 local room_factory = Rooms.new(self, "random_room")
-local vault_factory = Rooms.new(self, "lesser_vault")
+local vault_factory = Rooms.new(self, "greater_vault")
 
+local nb_vault = 0
 local rooms = {}
 for i = 1, 20 do
-	local proom = (rng.percent(20) and vault_factory or room_factory):generateRoom()
+	local proom = (nb_vault > 0 and vault_factory or room_factory):generateRoom()
 	local pos = proom and tm:findRandomArea(nil, tm.data_size, proom.data_w, proom.data_h, '#', 1)
 	if pos then
 		tm:merge(pos, proom:build())
 		rooms[#rooms+1] = proom
+		nb_vault = nb_vault - 1
 	end
 end
 
@@ -54,15 +56,19 @@ for i = 1, 20 do
 	end
 end
 
-if not loadMapScript("lib/connect_rooms_multi", {map=tm, rooms=rooms, edges_surplus=0}) then return self:regenerate() end
+if not loadMapScript("lib/connect_rooms_multi", {map=tm, rooms=rooms, door_chance=60, edges_surplus=0}) then return self:redo() end
 -- loadMapScript("lib/connect_rooms_multi", {map=tm, rooms=rooms})
 
 
 self:setEntrance(tm:locateTile('<'))
 self:setExit(rooms[#rooms]:centerPoint()) tm:put(rooms[#rooms]:centerPoint(), '>')
 
+
 -- Elimitate the rest
--- if tm:eliminateByFloodfill{'#', 'T'} < 600 then return self:regenerate() end
+-- if tm:eliminateByFloodfill{'#', 'T'} < 600 then return self:redo() end
+
+local spot = tm:point(1, 1)
+loadMapScript("lib/subvault", {map=tm, spot=spot, char="V"})
 
 tm:printResult()
 
diff --git a/game/modules/tome/data/zones/test/objects.lua b/game/modules/tome/data/zones/test/objects.lua
index e2b79283d12a415be191023882488649f3d6c74e..8e5dace8f7abff0b59c8dfdd0780ac886951387b 100644
--- a/game/modules/tome/data/zones/test/objects.lua
+++ b/game/modules/tome/data/zones/test/objects.lua
@@ -17,4 +17,4 @@
 -- Nicolas Casalini "DarkGod"
 -- darkgod@te4.org
 
----load("/data/general/objects/objects-maj-eyal.lua")
+load("/data/general/objects/objects-maj-eyal.lua")
diff --git a/game/modules/tome/data/zones/test/zone.lua b/game/modules/tome/data/zones/test/zone.lua
index 2b7d9755e336f3a054246078e47efa015ffe3372..d3e9efe773c2bb96072da2876ceecbec54fd085a 100644
--- a/game/modules/tome/data/zones/test/zone.lua
+++ b/game/modules/tome/data/zones/test/zone.lua
@@ -24,8 +24,8 @@ return {
 	max_level = 4,
 	decay = {300, 800},
 	actor_adjust_level = function(zone, level, e) return zone.base_level + e:getRankLevelAdjust() + level.level-1 + rng.range(-1,2) end,
-	width = 80, height = 80,
-	-- all_remembered = true,
+	width = 50, height = 50,
+	all_remembered = true,
 	all_lited = true,
 	no_level_connectivity = true,