Created
December 2, 2012 19:00
-
-
Save deveah/4190454 to your computer and use it in GitHub Desktop.
Cell-based dungeon generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
map = {} | |
map.width = 79 | |
map.height = 21 | |
map.cellWidth = 13 | |
map.cellHeight = 7 | |
map.rooms = {} | |
function isLegal( x, y ) | |
return x > 0 and y > 0 and x <= map.width and y <= map.height | |
end | |
function initMap() | |
for i = 1, map.width do | |
map[i] = {} | |
for j = 1, map.height do | |
map[i][j] = "#" | |
end | |
end | |
map.rooms = {} | |
end | |
function showMap() | |
for j = 1, map.height do | |
for i =1, map.width do | |
io.write( map[i][j] ) | |
end | |
io.write( "\n" ) | |
end | |
end | |
function digRoom( x, y, w, h ) | |
for i = x, x+w do | |
for j = y, y+h do | |
if isLegal( i, j ) then map[i][j] = "." end | |
end | |
end | |
end | |
function digCooridor( x1, y1, x2, y2 ) | |
local cx, cy, xo, yo = x1, y1, 0, 0 | |
if x2 > x1 then | |
xo = 1 | |
else | |
xo = -1 | |
end | |
if y2 > y1 then | |
yo = 1 | |
else | |
yo = -1 | |
end | |
while cx ~= x2 do | |
if isLegal( cx, cy ) then | |
if map[cx][cy] == "#" then | |
map[cx][cy] = "," | |
end | |
end | |
cx = cx + xo | |
end | |
while cy ~= y2 do | |
if isLegal( cx, cy ) then | |
if map[cx][cy] == "#" then | |
map[cx][cy] = "," | |
end | |
end | |
cy = cy + yo | |
end | |
end | |
function closestRoom( r, loopChance ) | |
local bd, bi = 999, 0 | |
local z = 0 | |
for i = 1, #map.rooms do | |
z = math.sqrt( math.pow( map.rooms[i].x-map.rooms[r].x, 2 ) + math.pow( map.rooms[i].y-map.rooms[r].y, 2 ) ) | |
if i ~= r and z < bd and ( not map.rooms[i].linked or math.random() < loopChance ) then | |
bd = z | |
bi = i | |
end | |
end | |
return bi | |
end | |
function allRoomsLinked() | |
for i = 1, #map.rooms do | |
if not map.rooms[i].linked then | |
return false | |
end | |
end | |
return true | |
end | |
--[[ | |
makeMap - the main dungeon building function | |
arguments: | |
roomChance - chance that a room will be placed in a cell, as the algorithm travels through all the cells | |
loopChance - the chance of making a cooridor loop | |
]] | |
function makeMap( roomChance, loopChance ) | |
local rx, ry, rw, rh = 0, 0, 0, 0 | |
local roomCount = 0 | |
for i = 0, math.floor( map.width / map.cellWidth )-1 do | |
for j = 0, math.floor( map.height / map.cellHeight )-1 do | |
if math.random() < roomChance then | |
while true do | |
rx = math.random( 2, map.cellWidth-1 ) | |
ry = math.random( 2, map.cellHeight-1 ) | |
rw = math.random( 2, map.cellWidth-1 ) | |
rh = math.random( 2, map.cellHeight-1 ) | |
if rx+rw < map.cellWidth and ry+rh < map.cellHeight then | |
break | |
end | |
end | |
digRoom( i*map.cellWidth+rx, j*map.cellHeight+ry, rw, rh ) | |
table.insert( map.rooms, { | |
x = i*map.cellWidth+rx + math.floor( rw/2 ), | |
y = j*map.cellHeight+ry + math.floor( rh/2 ), | |
linked = false | |
} ) | |
roomCount = roomCount + 1 | |
end | |
end | |
end | |
local ra = math.random( 1, #map.rooms ) | |
local rb = 0 | |
map.rooms[ra].linked = true | |
while not allRoomsLinked() do | |
rb = closestRoom( ra, loopChance ) | |
if rb ~= 0 then | |
digCooridor( map.rooms[ra].x, map.rooms[ra].y, map.rooms[rb].x, map.rooms[rb].y ) | |
if map.rooms[ra].linked then | |
map.rooms[rb].linked = true | |
end | |
ra = rb | |
end | |
end | |
return roomCount | |
end | |
function countNeighbours( x, y, t ) | |
local r = 0 | |
for i = x-1, x+1 do | |
for j = y-1, y+1 do | |
if isLegal( i, j ) then | |
if map[i][j] == t then r = r + 1 end | |
end | |
end | |
end | |
return r | |
end | |
function postProcess() | |
for i = 2, map.width-1 do | |
for j = 2, map.height-1 do | |
if countNeighbours( i, j, "." ) > 1 and countNeighbours( i, j, "," ) < 4 and map[i][j] == "," and | |
( ( map[i-1][j] == "#" and map[i+1][j] == "#" ) or | |
( map[i][j-1] == "#" and map[i][j+1] == "#" ) ) then | |
map[i][j] = "+" | |
end | |
end | |
end | |
for i = 1, map.width do | |
for j = 1, map.height do | |
if map[i][j] == "," then map[i][j] = "." end | |
end | |
end | |
for i = 1, map.width do | |
for j = 1, map.height do | |
if countNeighbours( i, j, "." ) == 0 then | |
map[i][j] = " " | |
end | |
end | |
end | |
end | |
math.randomseed( os.time() ) | |
initMap() | |
r = makeMap( 0.5, 0.5 ) | |
postProcess() | |
showMap() | |
print( r .. " rooms dug" ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment