feat(dungeon): add seed-derived cached floors
This commit is contained in:
1 parent
7e205a548f
commit
05541457e3
1 file changed
+60
@@ -0,0 +1,60 @@
|
||||
-- Owns every floor. Each level's layout is derived from the world seed and its
|
||||
-- depth alone, through a private rng that never touches the world rng stream, so
|
||||
-- a floor generates identically no matter when it is first entered. Generated
|
||||
-- floors are cached, which is what makes revisiting one restore its exact state.
|
||||
|
||||
local Rng = require("rng")
|
||||
local Builder = require("builder")
|
||||
local Level = require("level")
|
||||
|
||||
local Dungeon = {}
|
||||
Dungeon.__index = Dungeon
|
||||
|
||||
local SALT = 0x9E3779B97F4A7C15
|
||||
|
||||
function Dungeon.new(worldSeed, options)
|
||||
return setmetatable({
|
||||
worldSeed = worldSeed,
|
||||
options = options or {},
|
||||
levels = {},
|
||||
}, Dungeon)
|
||||
end
|
||||
|
||||
function Dungeon:levelSeed(depth)
|
||||
return math.tointeger(self.worldSeed ~ (depth * SALT)) or 0
|
||||
end
|
||||
|
||||
function Dungeon:get(depth)
|
||||
if not self.levels[depth] then
|
||||
local rng = Rng.new(self:levelSeed(depth))
|
||||
self.levels[depth] = Builder.build(depth, rng, self.options)
|
||||
end
|
||||
return self.levels[depth]
|
||||
end
|
||||
|
||||
function Dungeon:isGenerated(depth)
|
||||
return self.levels[depth] ~= nil
|
||||
end
|
||||
|
||||
function Dungeon:toData()
|
||||
local depths = {}
|
||||
for depth in pairs(self.levels) do
|
||||
depths[#depths + 1] = depth
|
||||
end
|
||||
table.sort(depths)
|
||||
local stored = {}
|
||||
for _, depth in ipairs(depths) do
|
||||
stored[#stored + 1] = { depth = depth, level = self.levels[depth]:toData() }
|
||||
end
|
||||
return { worldSeed = self.worldSeed, options = self.options, levels = stored }
|
||||
end
|
||||
|
||||
function Dungeon.fromData(snapshot)
|
||||
local dungeon = Dungeon.new(snapshot.worldSeed, snapshot.options)
|
||||
for _, entry in ipairs(snapshot.levels) do
|
||||
dungeon.levels[entry.depth] = Level.fromData(entry.level)
|
||||
end
|
||||
return dungeon
|
||||
end
|
||||
|
||||
return Dungeon
|
||||
Reference in new issue
Block a user