feat: build out builder
This commit is contained in:
1 parent
364ea34db4
commit
72e2969146
1 file changed
+131
+131
@@ -855,14 +855,145 @@ function Builder.build(depth, rng, options)
|
||||
-- can never end up sealed unreachably deep inside solid rock no digger
|
||||
-- could ever find. Its monster and loot markers (see gen/prefab.lua) draw
|
||||
-- from the same eligible roster and item tables every earlier pass in this
|
||||
-- floor already used. Drawn dead last of all before the grave below -
|
||||
-- which must stay the true last word (see its own comment) - so this can
|
||||
-- never perturb any earlier system's rng sequence either.
|
||||
local prefabVaults = {}
|
||||
if depth >= 3 and rng:chance(1, 5) then
|
||||
local vault = Prefab.vaults[rng:range(1, #Prefab.vaults)]
|
||||
local w, h = Prefab.size(vault)
|
||||
local vaultReach = reachSet(map, upX, upY, false)
|
||||
for _ = 1, 40 do
|
||||
local ox = rng:range(2, map.width - w)
|
||||
local oy = rng:range(2, map.height - h)
|
||||
if Prefab.fits(map, vault, ox, oy) then
|
||||
local untouched = true
|
||||
for y = oy, oy + h - 1 do
|
||||
for x = ox, ox + w - 1 do
|
||||
if map:get(x, y) ~= Tiles.WALL then untouched = false end
|
||||
end
|
||||
end
|
||||
local bordersReachable = false
|
||||
for y = oy - 1, oy + h do
|
||||
for x = ox - 1, ox + w do
|
||||
local onPerimeter = x < ox or x > ox + w - 1 or y < oy or y > oy + h - 1
|
||||
if onPerimeter and map:inBounds(x, y) and vaultReach[map:index(x, y)] then
|
||||
bordersReachable = true
|
||||
end
|
||||
end
|
||||
end
|
||||
if untouched and bordersReachable then
|
||||
local stamp = Prefab.stamp(map, vault, ox, oy)
|
||||
for _, spot in ipairs(stamp.treasure) do
|
||||
floorItems[#floorItems + 1] = { x = spot.x, y = spot.y, item = Vaults.treasure(rng, depth) }
|
||||
mark(spot.x, spot.y)
|
||||
end
|
||||
for _, spot in ipairs(stamp.loot) do
|
||||
floorItems[#floorItems + 1] = { x = spot.x, y = spot.y, item = rollItem(rng, depth) }
|
||||
mark(spot.x, spot.y)
|
||||
end
|
||||
for _, spot in ipairs(stamp.monsters) do
|
||||
local spec = eligible[rng:range(1, #eligible)]
|
||||
local monster = Monsters.create(spec, #entities + 1, spot.x, spot.y, depth)
|
||||
monster.awareness = Stealth.DORMANT
|
||||
entities[#entities + 1] = monster
|
||||
mark(spot.x, spot.y)
|
||||
end
|
||||
prefabVaults[#prefabVaults + 1] = { name = stamp.name, x = ox, y = oy, w = w, h = h }
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- A net turns up from depth five on, rarer than a miner's pick, drawn dead
|
||||
-- last of all - after even the prefab vault pass above - so it can never
|
||||
-- perturb any earlier system's rng sequence: the one way a run carries the
|
||||
-- means to subdue a battered monster alive instead of finishing it off
|
||||
-- (see captives.lua), rather than a strictly worse copy of an ordinary
|
||||
-- weapon. Gated this deep so it can never turn up in the fixed shallow
|
||||
-- worlds the win-condition tests build with a low --maxDepth.
|
||||
if depth >= 5 and rng:chance(1, 6) then
|
||||
local x, y = pickFree(reachable, rng, freeFloor)
|
||||
if x then
|
||||
floorItems[#floorItems + 1] = { x = x, y = y, item = Items.net() }
|
||||
mark(x, y)
|
||||
end
|
||||
end
|
||||
|
||||
-- A rift shard turns up from depth four on, rarer than a net, drawn dead
|
||||
-- last of all - after the net above - so it can never perturb any earlier
|
||||
-- system's rng sequence: fuel for the one crossing a rift (below) actually
|
||||
-- costs (see branches.lua), found a couple of floors ahead of where a rift
|
||||
-- can itself first appear so a run always has a real chance to be carrying
|
||||
-- one the day it matters.
|
||||
if depth >= 4 and rng:chance(1, 6) then
|
||||
local x, y = pickFree(reachable, rng, freeFloor)
|
||||
if x then
|
||||
floorItems[#floorItems + 1] = { x = x, y = y, item = Items.riftstone() }
|
||||
mark(x, y)
|
||||
end
|
||||
end
|
||||
|
||||
-- A rift tears open rarer still, only from depth six on, drawn dead last
|
||||
-- of all - after the shard above - so it can never perturb any earlier
|
||||
-- system's rng sequence: a shimmering, unstable seam in the floor a
|
||||
-- carried rift shard alone can stabilize into a crossing onto a short,
|
||||
-- harsher pocket floor (see branches.lua and Game:enterRift). Plain
|
||||
-- position-keyed level data exactly like a shrine or a node, never a tile
|
||||
-- of its own, so it needs no new entry in tiles.lua.
|
||||
local rifts = {}
|
||||
if depth >= 6 and rng:chance(1, 8) then
|
||||
local x, y = pickFree(reachable, rng, freeFloor)
|
||||
if x then
|
||||
rifts[#rifts + 1] = { x = x, y = y }
|
||||
mark(x, y)
|
||||
end
|
||||
end
|
||||
|
||||
-- A previous run's grave turns up rarer than a pick, dead last of all -
|
||||
-- after the lockpick, chest, secret door, biome, gate and net pass above -
|
||||
-- so it can never perturb any earlier system's rng sequence: cross-run
|
||||
-- bones (see graves.lua), rolled only when the caller actually supplies
|
||||
-- any - a run without --meta, or a fresh meta with no recorded deaths
|
||||
-- yet, makes no extra rng draw here at all, so its floors stay
|
||||
-- byte-identical to a build with no graves system in play.
|
||||
if options and options.graves and #options.graves > 0 then
|
||||
local eligibleGraves = Graves.eligibleFor(options.graves, depth)
|
||||
if #eligibleGraves > 0 and rng:chance(1, 5) then
|
||||
local x, y = pickFree(reachable, rng, freeFloor)
|
||||
if x then
|
||||
local grave = eligibleGraves[rng:range(1, #eligibleGraves)]
|
||||
floorItems[#floorItems + 1] = { x = x, y = y, item = Graves.floorItem(grave) }
|
||||
mark(x, y)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Level.new({
|
||||
depth = depth,
|
||||
generator = generator,
|
||||
weather = weather,
|
||||
biome = biome.key,
|
||||
map = map,
|
||||
entities = entities,
|
||||
floorItems = floorItems,
|
||||
traps = traps,
|
||||
lights = lights,
|
||||
hazards = hazards,
|
||||
shrines = shrines,
|
||||
questBoards = questBoards,
|
||||
cauldrons = cauldrons,
|
||||
nodes = nodes,
|
||||
chests = chests,
|
||||
vaultLevers = vaultLevers,
|
||||
vaultDoors = vaultDoors,
|
||||
secretDoors = secretDoors,
|
||||
blocks = blocks,
|
||||
plates = plates,
|
||||
gates = gates,
|
||||
prefabVaults = prefabVaults,
|
||||
rifts = rifts,
|
||||
dark = dark,
|
||||
explored = {},
|
||||
upX = upX, upY = upY,
|
||||
|
||||
Reference in new issue
Block a user