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