generated from PrismRL/prism-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlevelgen.lua
More file actions
101 lines (82 loc) · 3.46 KB
/
levelgen.lua
File metadata and controls
101 lines (82 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
local PARTITIONS = 3
--- @param rng RNG
--- @param player Actor
--- @param width integer
--- @param height integer
return function(rng, player, width, height)
local builder = prism.MapBuilder(prism.cells.Wall)
-- Fill the map with random noise of pits and walls.
local nox, noy = rng:random(1, 10000), rng:random(1, 10000)
for x = 1, width do
for y = 1, height do
local noise = love.math.perlinNoise(x / 5 + nox, y / 5 + noy)
local cell = noise > 0.5 and prism.cells.Wall or prism.cells.Pit
builder:set(x, y, cell())
end
end
-- Create rooms in each of the partitions.
--- @type table<number, Rectangle>
local rooms = {}
local missing = prism.Vector2(rng:random(0, PARTITIONS - 1), rng:random(0, PARTITIONS - 1))
local pw, ph = math.floor(width / PARTITIONS), math.floor(height / PARTITIONS)
local minrw, minrh = math.floor(pw / 3), math.floor(ph / 3)
local maxrw, maxrh = pw - 2, ph - 2 -- Subtract 2 to ensure there's a margin.
for px = 0, PARTITIONS - 1 do
for py = 0, PARTITIONS - 1 do
if not missing:equals(px, py) then
local rw, rh = rng:random(minrw, maxrw), rng:random(minrh, maxrh)
local x = rng:random(px * pw + 1, (px + 1) * pw - rw - 1)
local y = rng:random(py * ph + 1, (py + 1) * ph - rh - 1)
local roomRect = prism.Rectangle(x, y, rw, rh)
rooms[prism.Vector2._hash(px, py)] = roomRect
builder:drawRectangle(x, y, x + rw, y + rh, prism.cells.Floor)
end
end
end
-- Helper function to connect two points with an L-shaped hallway.
--- @param a Rectangle
--- @param b Rectangle
local function createLShapedHallway(a, b)
if not a or not b then return end
local ax, ay = a:center():floor():decompose()
local bx, by = b:center():floor():decompose()
-- Randomly choose one of two L-shaped tunnel patterns for variety.
if rng:random() > 0.5 then
builder:drawLine(ax, ay, bx, ay, prism.cells.Floor)
builder:drawLine(bx, ay, bx, by, prism.cells.Floor)
else
builder:drawLine(ax, ay, ax, by, prism.cells.Floor)
builder:drawLine(ax, by, bx, by, prism.cells.Floor)
end
end
for hash, currentRoom in pairs(rooms) do
local px, py = prism.Vector2._unhash(hash)
createLShapedHallway(currentRoom, rooms[prism.Vector2._hash(px + 1, py)])
createLShapedHallway(currentRoom, rooms[prism.Vector2._hash(px, py + 1)])
end
-- Choose the first room (top-left partition) to place the player.
local startRoom
while not startRoom do
local x, y = rng:random(0, PARTITIONS - 1), rng:random(0, PARTITIONS - 1)
startRoom = rooms[prism.Vector2._hash(x, y)]
end
local playerPos = startRoom:center():floor()
builder:addActor(player, playerPos.x, playerPos.y)
for _, room in pairs(rooms) do
if room ~= startRoom then
local cx, cy = room:center():floor():decompose()
builder:addActor(prism.actors.Kobold(), cx, cy)
end
end
builder:addPadding(1, prism.cells.Wall)
--- @type Rectangle[]
local availableRooms = {}
for _, room in pairs(rooms) do
if room ~= startRoom then table.insert(availableRooms, room) end
end
local stairRoom = availableRooms[rng:random(1, #availableRooms)]
local corners = stairRoom:toCorners()
local randCorner = corners[rng:random(1, #corners)]
builder:addActor(prism.actors.Stairs(), randCorner.x, randCorner.y)
return builder
end