Skip to content
Snippets Groups Projects
Commit 1df2aa3e authored by dg's avatar dg
Browse files

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
parent 518eb044
No related branches found
No related tags found
No related merge requests found
-- 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
......@@ -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
......
......@@ -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",
......
......@@ -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",
},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment