From 1df2aa3e37e9b78c7017b71dbc063e7832fddaed Mon Sep 17 00:00:00 2001
From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54>
Date: Sat, 22 May 2010 01:48:51 +0000
Subject: [PATCH] add Cavern level generator, also based simplex noise and some
 floodfill the flooded cave now uses the cavern generator

git-svn-id: http://svn.net-core.org/repos/t-engine4@670 51575b47-30f0-44d4-a5cc-537603b46e54
---
 game/engine/generator/map/Cavern.lua          | 146 ++++++++++++++++++
 game/engine/generator/map/Forest.lua          |   3 +-
 .../tome/data/zones/flooded-cave/zone.lua     |  13 +-
 game/modules/tome/data/zones/test/zone.lua    |  11 +-
 4 files changed, 160 insertions(+), 13 deletions(-)
 create mode 100644 game/engine/generator/map/Cavern.lua

diff --git a/game/engine/generator/map/Cavern.lua b/game/engine/generator/map/Cavern.lua
new file mode 100644
index 0000000000..ce221308c0
--- /dev/null
+++ b/game/engine/generator/map/Cavern.lua
@@ -0,0 +1,146 @@
+-- TE4 - T-Engine 4
+-- 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
+
+require "engine.class"
+local Map = require "engine.Map"
+require "engine.Generator"
+module(..., package.seeall, class.inherit(engine.Generator))
+
+function _M:init(zone, map, level, data)
+	engine.Generator.init(self, zone, map, level)
+	self.data = data
+	self.grid_list = zone.grid_list
+	self.zoom = data.zoom or 12
+	self.hurst = data.hurst or 0.2
+	self.lacunarity = data.lacunarity or 4
+	self.octave = data.octave or 1
+	self.min_floor = data.min_floor or 900
+	self.noise = data.noise or "simplex"
+end
+
+function _M:resolve(c)
+	local res = self.data[c]
+	if type(res) == "function" then
+		return res()
+	elseif type(res) == "table" then
+		return res[rng.range(1, #res)]
+	else
+		return res
+	end
+end
+
+function _M:generate(lev, old_lev)
+	print("Generating cavern")
+	local noise = core.noise.new(2, self.hurst, self.lacunarity)
+	local fills = {}
+	local opens = {}
+	local list = {}
+	for i = 0, self.map.w - 1 do
+		opens[i] = {}
+		for j = 0, self.map.h - 1 do
+			if noise[self.noise](noise, self.zoom * i / self.map.w, self.zoom * j / self.map.h, self.octave) > 0 then
+				self.map(i, j, Map.TERRAIN, self.grid_list[self:resolve("floor")]:clone())
+				opens[i][j] = #list+1
+				list[#list+1] = {x=i, y=j}
+			else
+				self.map(i, j, Map.TERRAIN, self.grid_list[self:resolve("wall")])
+			end
+		end
+	end
+
+	local floodFill floodFill = function(x, y)
+		local q = {{x=x,y=y}}
+		local closed = {}
+		while #q > 0 do
+			local n = table.remove(q, 1)
+			if opens[n.x] and opens[n.x][n.y] then
+				closed[#closed+1] = n
+				list[opens[n.x][n.y]] = nil
+				opens[n.x][n.y] = nil
+				q[#q+1] = {x=n.x-1, y=n.y}
+				q[#q+1] = {x=n.x, y=n.y+1}
+				q[#q+1] = {x=n.x+1, y=n.y}
+				q[#q+1] = {x=n.x, y=n.y-1}
+
+				q[#q+1] = {x=n.x+1, y=n.y-1}
+				q[#q+1] = {x=n.x+1, y=n.y+1}
+				q[#q+1] = {x=n.x-1, y=n.y-1}
+				q[#q+1] = {x=n.x-1, y=n.y+1}
+			end
+		end
+		return closed
+	end
+
+	-- Process all open spaces
+	local groups = {}
+	while next(list) do
+		local i, l = next(list)
+		local closed = floodFill(l.x, l.y)
+		groups[#groups+1] = {id=id, list=closed}
+		print("Floodfill group", i, #closed)
+	end
+	-- If nothing exists, regen
+	if #groups == 0 then return self:generate(lev, old_lev) end
+
+	-- Sort to find the biggest group
+	table.sort(groups, function(a,b) return #a.list < #b.list end)
+	local g = groups[#groups]
+	if #g.list >= self.min_floor then
+		print("Ok floodfill")
+		for i = 1, #groups-1 do
+			for j = 1, #groups[i].list do
+				local jn = groups[i].list[j]
+				self.map(jn.x, jn.y, Map.TERRAIN, self.grid_list[self:resolve("wall")])
+			end
+		end
+	else
+		return self:generate(lev, old_lev)
+	end
+
+	return self:makeStairsInside(lev, old_lev, {})
+end
+
+--- Create the stairs inside the level
+function _M:makeStairsInside(lev, old_lev, spots)
+	-- Put down stairs
+	local dx, dy
+	if lev < self.zone.max_level or self.data.force_last_stair then
+		while true do
+			dx, dy = rng.range(1, self.map.w - 1), rng.range(1, self.map.h - 1)
+			if not self.map:checkEntity(dx, dy, Map.TERRAIN, "block_move") and not self.map.room_map[dx][dy].special then
+				self.map(dx, dy, Map.TERRAIN, self.grid_list[self:resolve("down")])
+				self.map.room_map[dx][dy].special = "exit"
+				break
+			end
+		end
+	end
+
+	-- Put up stairs
+	local ux, uy
+	while true do
+		ux, uy = rng.range(1, self.map.w - 1), rng.range(1, self.map.h - 1)
+		if not self.map:checkEntity(ux, uy, Map.TERRAIN, "block_move") and not self.map.room_map[ux][uy].special then
+			self.map(ux, uy, Map.TERRAIN, self.grid_list[self:resolve("up")])
+			self.map.room_map[ux][uy].special = "exit"
+			break
+		end
+	end
+
+	return ux, uy, dx, dy, spots
+end
diff --git a/game/engine/generator/map/Forest.lua b/game/engine/generator/map/Forest.lua
index 619bb6df75..6b46c8d3ea 100644
--- a/game/engine/generator/map/Forest.lua
+++ b/game/engine/generator/map/Forest.lua
@@ -64,7 +64,8 @@ function _M:generate(lev, old_lev)
 		end
 	end
 
-	local ux, uy, dx, dy, spots
+	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)
 	else
diff --git a/game/modules/tome/data/zones/flooded-cave/zone.lua b/game/modules/tome/data/zones/flooded-cave/zone.lua
index e417511a60..49490c3ae7 100644
--- a/game/modules/tome/data/zones/flooded-cave/zone.lua
+++ b/game/modules/tome/data/zones/flooded-cave/zone.lua
@@ -24,7 +24,7 @@ return {
 	max_level = 2,
 	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 = 100, height = 100,
+	width = 70, height = 70,
 	all_remembered = true,
 	all_lited = true,
 --	persistant = "zone",
@@ -34,12 +34,11 @@ return {
 	color_obscure = {0.5*0.6, 1*0.6, 0.8*0.6, 1},
 	generator =  {
 		map = {
-			class = "engine.generator.map.Roomer",
-			nb_rooms = 50,
-			edge_entrances = {4,6},
-			rooms = {"forest_clearing","money_vault"},
-			['.'] = "WATER_FLOOR",
-			['#'] = "WATER_WALL",
+			class = "engine.generator.map.Cavern",
+			zoom = 16,
+			min_floor = 1200,
+			floor = "WATER_FLOOR",
+			wall = "WATER_WALL",
 			up = "UP",
 			down = "DOWN",
 			door = "WATER_FLOOR",
diff --git a/game/modules/tome/data/zones/test/zone.lua b/game/modules/tome/data/zones/test/zone.lua
index 4039e72833..2c9aeac7b2 100644
--- a/game/modules/tome/data/zones/test/zone.lua
+++ b/game/modules/tome/data/zones/test/zone.lua
@@ -24,16 +24,17 @@ 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 = 50, height = 50,
+	width = 70, height = 70,
 	all_remembered = true,
 	all_lited = true,
 --	persistant = "zone",
 	generator =  {
 		map = {
-			class = "engine.generator.map.GOL",
-			edge_entrances = {4,6},
-			floor = "GRASS",
-			wall = "TREE",
+			class = "engine.generator.map.Cavern",
+			zoom = 16,
+			min_floor = 1200,
+			floor = "FLOOR",
+			wall = "WALL",
 			up = "UP",
 			down = "DOWN",
 		},
-- 
GitLab