## Need help with random map/city generator

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Jasoco
Inner party member
Posts: 3651
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

### Re: Need help with random map/city generator

It shows up now. But the others don't show up for anyone but you because you've already seen them and they're in your browser cache. When you use image hosts, make sure to either use the image URL they supply you or the one that has UBB IMG tags around it. (On that host you used before, you need to click the "Show codes" link to see them. I suggest just using Imgur since they don't hide that stuff from people. It's stupid to hide that stuff. It's the whole point of an image host.)

Alternatively, just use the forum's file attachment system when posting.

Rickton wrote:Do you have any code uploaded anywhere of your method of using that kind of generation? It seems really interesting, but he talks about "sliding" the new room around until it fits, and doing that for every single new room. Is there some kind of algorithm or something for that, or a way of doing it intelligently? Because it seems like it'd be pretty inefficient and slow to do that dozens of times for a full level.
My code is a mess that would make you pull your hair out. Instead code it yourself following the description in the article. It's not that easy though. It's quite complex. And only one of many methods.

Imaculata
Party member
Posts: 102
Joined: Mon Aug 10, 2015 2:51 pm

### Re: Need help with random map/city generator

Thanks, will do.

I just added a messy bit of code that is supposed to carve out doorways in between the rooms. But it doesn't seem to be working quite right. Occasionally it only carves out half the doorway, and then stops at the next room. I probably messed something up. Maybe its not reliably picking the correct tiles to replace with floor tiles. Or maybe something is getting overwritten.

Once I get it to work, I'll start adding the doors themselves between the rooms.

louie999
Prole
Posts: 46
Joined: Fri Mar 06, 2015 9:01 am

### Re: Need help with random map/city generator

Ok, so I tried making a map generator, I also put the t.console in conf.lua to true because I laid down alot of print() functions around the map generator code so I can really make sure that it's working properly, but my problem is some time after the map generation begins then my game will suddenly freeze and not respond so I have to close it is it because there's too many loops? code:

Code: Select all

-- Variables
local generating = false
local gen_default = false
local TILES = wazmb.ALLTILES
local done = false
local lmt = love.math
wazmb.MAP = {}
wazmb.MAP.X = 0
wazmb.MAP.Y = 0
-----
local function newBuilding(x, y)
TILES[x][y] = {tiletype = 3, tilesetn = 1}
TILES[x+1][y] = {tiletype = 3, tilesetn = 7}
TILES[x+2][y] = {tiletype = 3, tilesetn = 2}
TILES[x][y+1] = {tiletype = 3, tilesetn = 3}
TILES[x+1][y+1] = {tiletype = 3, tilesetn = 4}
TILES[x+2][y+1] = {tiletype = 3, tilesetn = 9}
TILES[x][y+2] = {tiletype = 3, tilesetn = 5}
TILES[x+1][y+2] = {tiletype = 3, tilesetn = 6}
TILES[x+1][y+2] = {tiletype = 3, tilesetn = 8}
end

local function tile_occupied(x, y)
if TILES[x][y].tilesetn ~= 0 then
return true
end
return false
end

local function GENERATE_DEFAULT_TILES(maxx, maxy)
local numx, numy = 0, 0
while gen_default do
local randx, randy = lmt.random(1, maxx), lmt.random(1, maxy)
if numx >= maxx and maxy >= maxy then gen_default = false end
if not tile_occupied(randx, randy) then
TILES[randx][randy] = {tiletype = 1, tilesetn = 1}
numx = numx + 1
numx = numy + 1
print("Placed default tile in "..randx..", "..randy)
end
end
wazmb.ALLTILES = TILES
done = true
print("Map generation done")
end

local function GENERATE_BUILDINGS(maxx, maxy, maxb)
print("Generating buildings...")
local cb = 0
print("1")
while generating do
local rand1 = math.random(1, 100)
local rand2 = math.random(1, 100)
local randx, randy = lmt.random(1, maxx), lmt.random(1, maxy)
if cb >= maxb then generating = false; gen_default = true end
if rand1 - rand2 >= 35 then
newBuilding(randx, randy)
print("Building generated at - "..randx..", "..randy)
cb = cb + 1
end
end
if gen_default then GENERATE_DEFAULT_TILES(maxx, maxy) end
end

function wazmb.GENERATOR_INIT(maxx, maxy, maxb)
print("Generating random map...")
if maxx ~= nil then
if maxx < 200 then maxx = 200 end
end
if maxy ~= nil then
if maxy < 200 then maxy = 200 end
end
local MAP_MAX_X = maxx or lmt.random(200, 500)
local MAP_MAX_Y = maxy or lmt.random(200, 500)
local MAXBUILD = maxb or lmt.random(20, 50)
wazmb.MAINCAM = wazmb.gamera.new(0, 0, MAP_MAX_X, MAP_MAX_Y)
for X = 1, MAP_MAX_X do
TILES[X] = {}
for Y = 1, MAP_MAX_Y do
print("Tile "..X..", "..Y)
TILES[X][Y] = {tiletype = 0, tilesetn = 0}
end
end
generating = true
local ok, err = pcall(GENERATE_BUILDINGS, MAP_MAX_X, MAP_MAX_Y, MAXBUILD)
if err then print(err) end
end

function wazmb.DRAW_MAP()
print("Drawing map...")
for X, map in ipairs(wazmb.ALLTILES) do
for Y, t in ipairs(map) do
local tiletype = wazmb._TILE._TILESET[t.tilesetn].q
local x, y = (X - 1) * wazmb._TILE._TILESIZE, (Y - 1) * wazmb._TILE._TILESIZE
lg.draw(wazmb._TILE._TILE_SET_, tiletype, x, y)
end
end
end

function wazmb.Map_Control()
if done then
local isDown = wazmb.lk.isDown
local cam = wazmb.MAINCAM
local t = {
["up"] = {x = 0, y = 10},
["down"] = {x = 0, y = -10},
["right"] = {x = 10, y = 0},
["left"] = {x = -10, y = 0}
}
if t[isDown] ~= nil then
wazmb.MAP.X = wazmb.MAP.X + t[isDown].x
wazmb.MAP.Y = wazmb.MAP.Y + t[isDown].y
end
cam:setPosition(wazmb.MAP.X, wazmb.MAP.Y)
end
end

Code: Select all

fun = true
school = true

function isItFun()
if school then
fun = false
end
if not fun then
me:explode()
end
end

Imaculata
Party member
Posts: 102
Joined: Mon Aug 10, 2015 2:51 pm

### Re: Need help with random map/city generator

You have less loops than I do, and my code finishes in less than a second. So I'm going to guess that the problem is most not related to the number of loops, but more likely caused by your loops getting stuck. I'm not sure if you are using the same method for creating random dungeons as I am. But what I did, was make sure that the crawlers were limited to a maximum length (in rooms), and a maximum number of attempts to find a suitable location to expand the maze to.

There's a high chance for error since my method of making a dungeon is very dumb. The crawler can easily corner itself without realizing it, so I made sure that after a certain number of tries, it simply gives up. Did you insert fail safes?

Jasoco
Inner party member
Posts: 3651
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

### Re: Need help with random map/city generator

You need to set a limit to the amount of loops that can run and use break to exit out of the loop if it gets to be too much. Also you can use love.timer.sleep(0.001) every few thousand loops to give some control back to the system if the loop is going to take a notably long time.

Nixola
Inner party member
Posts: 1941
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

### Re: Need help with random map/city generator

You should call love.event.pump every once in a while during said loops too, so that the OS doesn't think it froze.
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
li = love.image
lg = love.graphics

Jasoco
Inner party member
Posts: 3651
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

### Re: Need help with random map/city generator

Basically in your while loop increment a counter and if it hits an arbitrary number of loops, pump the events and sleep the timer for 0.001 seconds and if you want you can also call love.graphics.clear(), draw some stuff and then love.graphics.present() to draw a "Generating..." message or even a progress bar with some work if you know a definite amount of time it should take.

Some pseudocode:

Code: Select all

local loops = 0
while whatever_you_are_doing do
-- Your code that takes a while goes here

if loops == 0 then
love.graphics.clear() -- Sets the window background to the background color
love.graphics.setColor(255,255,255) -- A color that is visible against the background color
love.graphics.print("Generating...", 10, 10)
love.graphics.present()
-- You could draw anything you want here really. Don't draw too much.
-- All you need is something to tell the user that the game is doing stuff.

love.timer.sleep(0.001)
love.event.pump()
end
loops = loops + 1
if loops > 10000 then loops = 0 end
end
Where 10000 above is a number you would figure out yourself based on how long each loop takes. If you set it too low you'll slow down your generation because the drawing and sleep time will add up way too much. If you set it too high the loop will run longer than the OS wants to wait and you might get the spinning cursor or Windows "Application is hanging" dialog. So tweak the value on a per loop basis.

louie999
Prole
Posts: 46
Joined: Fri Mar 06, 2015 9:01 am

### Re: Need help with random map/city generator

Thanks guys, the map generator is still not 100% complete but atleast the loop problem is fixed

Code: Select all

local function GENERATE_BUILDINGS(maxsize, maxb)
local cb = 0
while generating do
local rand1 = math.random(1, 100)
local rand2 = math.random(1, 100)
local randx, randy = lmt.random(1, maxsize), lmt.random(1, maxsize)
if cb >= maxb then generating = false; gen_default = true end
if rand1 - rand2 >= 35 then
newBuilding(randx, randy)
wazmb.MAP.X = randx
wazmb.MAP.Y = randy
cb = cb + 1
end
end
wazmb.ALLTILES = TILES
end

function wazmb.GENERATOR_INIT(maxsize, maxb)
if maxsize ~= nil then
if maxsize < 200 then maxsize = 200 end
end
local i = 0
local MAP_MAX_SIZE = maxsize or lmt.random(200, 500)
local MAXBUILD = maxb or lmt.random(20, 50)
wazmb.MAINCAM = wazmb.gamera.new(0, 0,  MAP_MAX_SIZE,  MAP_MAX_SIZE)
for X = 1,  MAP_MAX_SIZE do
TILES[X] = {}
for Y = 1,  MAP_MAX_SIZE do
if i >= 500 then love.event.pump(); love.timer.sleep(0.001); i = 0 end
TILES[X][Y] = {tiletype = 1, tilesetn = 10}
i = i + 1
end
end
generating = true
GENERATE_BUILDINGS(MAP_MAX_SIZE, MAXBUILD)
end

Code: Select all

fun = true
school = true

function isItFun()
if school then
fun = false
end
if not fun then
me:explode()
end
end

Imaculata
Party member
Posts: 102
Joined: Mon Aug 10, 2015 2:51 pm

### Re: Need help with random map/city generator

Excellent work Louie! In the case of my Zelda clone, the crawler can only go in 4 directions. So I have it randomly pick one of the 4 directions, and check if it can build a room there. If it can't find a room after 24 tries, it finishes the process, and declares the chain as done. 24 is a much smaller number than 10,000 of course. But the difference in calculation time is probably merely a fraction of a second. I figured that it wouldn't take that many tries to find a suitable room, if there are only 4 options to randomly choose from.

When I start adding the sub-chains, then the crawlers will need more fail-safes. Because what if I try to create 4 chains, but the third chain has already used up all available empty rooms? I'll need to make sure that the crawler gives up after a while, and continues with the dungeon creation process.

ArchAngel075
Party member
Posts: 317
Joined: Mon Jun 24, 2013 5:16 am

### Re: Need help with random map/city generator

I had once used a tiled like method to make a dungeon crawler.

First i would place a root room - it is always a static x by y room.

Next iterate n times where n is the number of rooms id like to add,
for each iteration pick a random room and check if it isn't fully neighbored. That is that it doesn't have a room in each 4 directions.
If it can take a room then for each direction do the following,
Pick a distance to place a corridor, then from the biggest size room possible to the smallest decreasing (width and height test separately) try and fit that room in so that it doesn't over lap other rooms, it can have shared walls with a existing room though.
If a possible fit is found then place the room and then carve a straight corridor between the two rooms.
after each successful wall placement for every room test if there if there is a room in any four directions and a random chance payed (~30% to do this else it ignores), if one is found then it forces them to have a corridor link.

With repeating in all four directions it can give up and mark a room as 'complete' if it has had all 4 directions exhausted (no rooms can fit if it tried on all four)
Repeat this process n times.

Note :
It was brutal making it, especially since i had to make rooms downsize and then center, and a issue when one room was evenly length on a wall and another had a odd sized length/breadth wall and the two wanted to corridor between one another.
It made amazing multi entranced connections and could squeeze the most of a tilemap. almost using up 80% of the tiles, only small bits of air that is around 2x2 in-between because of the attempt at force downsizing a room until it fits.

### Who is online

Users browsing this forum: Google [Bot] and 12 guests