From e824fa467e637cf680d30460d7843e9c639ffce6 Mon Sep 17 00:00:00 2001
From: Wuzzy <Wuzzy2@mail.ru>
Date: Thu, 22 Aug 2019 14:50:26 +0200
Subject: [PATCH] Randomly rotate pyramids

---
 init.lua | 71 ++++++++++++++++++++++++++++++++++++++++----------------
 room.lua | 54 +++++++++++++++++++++++++++++++++++++-----
 2 files changed, 99 insertions(+), 26 deletions(-)

diff --git a/init.lua b/init.lua
index 2848caa..61fbcc6 100644
--- a/init.lua
+++ b/init.lua
@@ -99,21 +99,46 @@ local function make_foundation_part(pos, set_to_stone)
 	end
 end
 
-local function make_entrance(pos, brick, sand, flood_sand)
-	local gang = {x=pos.x+10,y=pos.y, z=pos.z}
+local function make_entrance(pos, rot, brick, sand, flood_sand)
+	local roffset_arr = {
+		{ x=0, y=0, z=1 }, -- front
+		{ x=-1, y=0, z=0 }, -- left
+		{ x=0, y=0, z=-1 }, -- back
+		{ x=1, y=0, z=0 }, -- right
+	}
+	local roffset = roffset_arr[rot + 1]
+	local way
+	if rot == 0 then
+		way = vector.add(pos, {x=11, y=0, z=0})
+	elseif rot == 1 then
+		way = vector.add(pos, {x=22, y=0, z=11})
+	elseif rot == 2 then
+		way = vector.add(pos, {x=11, y=0, z=22})
+	else
+		way = vector.add(pos, {x=0, y=0, z=11})
+	end
 	local max_sand_height = math.random(1,3)
-	for iz=0,6,1 do
+	for ie=0,6,1 do
 		local sand_height = math.random(1,max_sand_height)
 		for iy=2,3,1 do
-			if flood_sand and iy <= sand_height and iz >= 3 then
-				minetest.set_node({x=gang.x+1,y=gang.y+iy,z=gang.z+iz}, {name=sand})
+			-- dig hallway
+			local way_dir = vector.add(vector.add(way, {x=0,y=iy,z=0}), vector.multiply(roffset, ie))
+			if flood_sand and iy <= sand_height and ie >= 3 then
+				minetest.set_node(way_dir, {name=sand})
 			else
-				minetest.remove_node({x=gang.x+1,y=gang.y+iy,z=gang.z+iz})
+				minetest.remove_node(way_dir)
 			end
-			if iz >=3 and iy == 3 then
-				minetest.set_node({x=gang.x,y=gang.y+iy+1,z=gang.z+iz}, {name=brick})
-				minetest.set_node({x=gang.x+1,y=gang.y+iy+1,z=gang.z+iz}, {name=brick})
-				minetest.set_node({x=gang.x+2,y=gang.y+iy+1,z=gang.z+iz}, {name=brick})
+			-- build decoration above entrance
+			if ie >=3 and iy == 3 then
+				local deco = {x=way_dir.x, y=way_dir.y+1,z=way_dir.z}
+				minetest.set_node(deco, {name=brick})
+				if rot == 0 or rot == 2 then
+					minetest.set_node(vector.add(deco, {x=-1, y=0, z=0}), {name=brick})
+					minetest.set_node(vector.add(deco, {x=1, y=0, z=0}), {name=brick})
+				else
+					minetest.set_node(vector.add(deco, {x=0, y=0, z=-1}), {name=brick})
+					minetest.set_node(vector.add(deco, {x=0, y=0, z=1}), {name=brick})
+				end
 			end
 		end
 	end
@@ -148,22 +173,28 @@ end
 local function make(pos, brick, sandstone, stone, sand, ptype, room_id)
 	-- Build pyramid
 	make_pyramid(pos, brick, sandstone, stone, sand)
+
+	local rot = math.random(0, 3)
 	-- Build room
-	local ok, msg, flood_sand = tsm_pyramids.make_room(pos, ptype, room_id)
+	local ok, msg, flood_sand = tsm_pyramids.make_room(pos, ptype, room_id, rot)
 	-- Place mummy spawner
 	local r = math.random(1,3)
-	if r == 1 then
+	-- 4 possible spawner positions
+	local spawner_posses = {
 		-- front
-		add_spawner({x=pos.x+11,y=pos.y+2, z=pos.z+17}, {x=0, y=0, z=-2})
-	elseif r == 2 then
-		-- right
-		add_spawner({x=pos.x+17,y=pos.y+2, z=pos.z+11}, {x=-2, y=0, z=0})
-	else
+		{{x=pos.x+11,y=pos.y+2, z=pos.z+5}, {x=0, y=0, z=2}},
 		-- left
-		add_spawner({x=pos.x+5,y=pos.y+2, z=pos.z+11}, {x=2, y=0, z=0})
-	end
+		{{x=pos.x+17,y=pos.y+2, z=pos.z+11}, {x=-2, y=0, z=0}},
+		-- back
+		{{x=pos.x+11,y=pos.y+2, z=pos.z+17}, {x=0, y=0, z=-2}},
+		-- right
+		{{x=pos.x+5,y=pos.y+2, z=pos.z+11}, {x=2, y=0, z=0}},
+	}
+	-- Delete the spawner position in which the entrance will be placed
+	table.remove(spawner_posses, (rot % 4) + 1)
+	add_spawner(spawner_posses[r][1], spawner_posses[r][2])
 	-- Build entrance
-	make_entrance({x=pos.x,y=pos.y, z=pos.z}, brick, sand, flood_sand)
+	make_entrance(pos, rot, brick, sand, flood_sand)
 	-- Done
 	minetest.log("action", "Created pyramid at ("..pos.x..","..pos.y..","..pos.z..")")
 	return ok, msg
diff --git a/room.lua b/room.lua
index 1a7ffd0..7648d8d 100644
--- a/room.lua
+++ b/room.lua
@@ -2,6 +2,8 @@ local S = minetest.get_translator("tsm_pyramids")
 
 -- ROOM LAYOUTS
 
+local ROOM_WIDTH = 9
+
 local room_types = {
 	-- Pillar room
 	{
@@ -587,7 +589,45 @@ local function replace2(str, iy, code_table)
 	return out..code_table[str]
 end
 
-function tsm_pyramids.make_room(pos, stype, room_id)
+local function get_flat_index(x, y, width)
+	return 1 + x + y * width
+end
+
+local function rotate_layout_single(layout, width)
+	local size = width*width
+	local new_layout = {}
+	for x=0, width-1 do
+		for y=0, width-1 do
+			local symbol = layout[get_flat_index((width-1) - y, x, width)]
+			-- Rotate chest
+			if symbol == "^" then
+				symbol = "<"
+			elseif symbol == "<" then
+				symbol = "v"
+			elseif symbol == "v" then
+				symbol = ">"
+			elseif symbol == ">" then
+				symbol = "^"
+			end
+			new_layout[get_flat_index(x, y, width)] = symbol
+		end
+	end
+	return new_layout
+end
+
+local function rotate_layout(layout, width, rotations)
+	local new_layout = table.copy(layout)
+	for r=1, rotations do
+		new_layout = rotate_layout_single(new_layout, width)
+	end
+	return new_layout
+end
+
+-- pos: Position to spawn pyramid
+-- stype: Sand type ("sandstone" or "desert")
+-- room_id: Room layout identified (see list of rooms above)
+-- rotations: Number of times to rotate the room (0-3)
+function tsm_pyramids.make_room(pos, stype, room_id, rotations)
 	local code_table = code_sandstone
 	if stype == "desert" then
 		code_table = code_desert
@@ -608,14 +648,15 @@ function tsm_pyramids.make_room(pos, stype, room_id)
 	if room_id < 1 or room_id > #room_types then
 		return false, S("Incorrect room type ID: @1", room_id)
 	end
-	local room = room_types[room_id]
+	local room = table.copy(room_types[room_id])
 	local chests = {}
 	local column_style = math.random(0,4)
+	local layout = rotate_layout(room.layout, ROOM_WIDTH, rotations)
 	if room.style == "yrepeat" then
 		for iy=0,4,1 do
 			for ix=0,8,1 do
 				for iz=0,8,1 do
-					local n_str = room.layout[tonumber(ix*9+iz+1)]
+					local n_str = layout[tonumber(ix*9+iz+1)]
 					local p2 = 0
 					if n_str == "<" then
 						p2 = 0
@@ -650,7 +691,7 @@ function tsm_pyramids.make_room(pos, stype, room_id)
 		end
 	end
 	if room.traps then
-		tsm_pyramids.make_traps(pos, stype)
+		tsm_pyramids.make_traps(pos, stype, rotations)
 	end
 	if sanded then
 		tsm_pyramids.flood_sand(pos, stype)
@@ -671,17 +712,18 @@ local shuffle_traps = function(chance)
 	end
 end
 
-function tsm_pyramids.make_traps(pos, stype)
+function tsm_pyramids.make_traps(pos, stype, rotations)
 	local code_table = code_sandstone
 	if stype == "desert" then
 		code_table = code_desert
 	end
 	shuffle_traps(math.random(10,100))
 	local hole = {x=pos.x+7,y=pos.y, z=pos.z+7}
+	local layout = rotate_layout(layout_traps, ROOM_WIDTH, rotations)
 	for iy=0,4,1 do
 		for ix=0,8,1 do
 			for iz=0,8,1 do
-				local n_str = layout_traps[tonumber(ix*9+iz+1)]
+				local n_str = layout[tonumber(ix*9+iz+1)]
 				local p2 = 0
 				minetest.set_node({x=hole.x+ix,y=hole.y-iy,z=hole.z+iz}, {name=replace2(n_str, iy, code_table), param2=p2})
 			end