Skip to content
Snippets Groups Projects
Commit e1147714 authored by dg's avatar dg
Browse files

roomer generator

git-svn-id: http://svn.net-core.org/repos/t-engine4@130 51575b47-30f0-44d4-a5cc-537603b46e54
parent 538e17ce
No related branches found
No related tags found
No related merge requests found
require "engine.class"
local Map = require "engine.Map"
require "engine.Generator"
module(..., package.seeall, class.inherit(engine.Generator))
function _M:init(map, grid_list, data)
engine.Generator.init(self, map)
self.data = data
self.data.tunnel_change = self.data.tunnel_change or 30
self.data.tunnel_random = self.data.tunnel_random or 10
self.data.tunnel_premature_end = self.data.tunnel_premature_end or 10
self.grid_list = grid_list
self.rooms = {}
for i, file in ipairs(data.rooms) do
table.insert(self.rooms, self:loadRoom(file))
end
self.room_map = {}
for i = 0, self.map.w - 1 do
self.room_map[i] = {}
for j = 0, self.map.h - 1 do
self.room_map[i][j] = {}
end
end
end
function _M:loadRoom(file)
local f = loadfile("/data/rooms/"..file..".lua")
local d = {}
setfenv(f, d)
local ret, err = f()
if not ret and err then error(err) end
-- Init the room with name and size
local t = { name=file, w=ret[1]:len(), h=#ret }
-- Read the room map
for j, line in ipairs(ret) do
local i = 1
for c in line:gmatch(".") do
t[i] = t[i] or {}
t[i][j] = c
i = i + 1
end
end
print("loaded room",file,t.w,t.h)
return t
end
function _M:resolve(c)
local res = self.data[c]
if type(res) == "function" then
return res()
elseif type(res) == "table" then
return res[rng.range(1, #res)]
else
return res
end
end
function _M:roomAlloc(room, id)
print("alloc", room.name)
local tries = 100
while tries > 0 do
local ok = true
local x, y = rng.range(1, self.map.w - 2 - room.w), rng.range(1, self.map.h - 2 - room.h)
-- Do we stomp ?
for i = 1, room.w do
for j = 1, room.h do
if self.room_map[i-1+x][j-1+y].room then ok = false break end
end
if not ok then break end
end
if ok then
-- ok alloc it
for i = 1, room.w do
for j = 1, room.h do
self.room_map[i-1+x][j-1+y].room = id
local c = room[i][j]
if c == '!' then
self.room_map[i-1+x][j-1+y].can_open = true
self.map(i-1+x, j-1+y, Map.TERRAIN, self.grid_list[self:resolve('#')])
else
self.map(i-1+x, j-1+y, Map.TERRAIN, self.grid_list[self:resolve(c)])
end
end
end
print("room allocated at", x, y,"with center",math.floor(x+(room.w-1)/2), math.floor(y+(room.h-1)/2))
return { id=id, x=x, y=y, cx=math.floor(x+(room.w-1)/2), cy=math.floor(y+(room.h-1)/2), room=room }
end
tries = tries - 1
end
return false
end
function _M:randDir()
local dirs = {4,6,8,2}
local d = dir_to_coord[dirs[rng.range(1, #dirs)]]
return d[1], d[2]
end
function _M:tunnelDir(x1, y1, x2, y2)
local xdir = (x1 == x2) and 0 or ((x1 < x2) and 1 or -1)
local ydir = (y1 == y2) and 0 or ((y1 < y2) and 1 or -1)
if xdir ~= 0 and ydir ~= 0 then
if rng.percent(50) then xdir = 0
else ydir = 0
end
end
return xdir, ydir
end
function _M:tunnel(x1, y1, x2, y2)
local xdir, ydir = self:tunnelDir(x1, y1, x2, y2)
print("tunneling from",x1, y1, "to", x2, y2, "initial dir", xdir, ydir)
local startx, starty = x1, y1
local tun = {}
local tries = 2000
while tries > 0 do
if rng.percent(self.data.tunnel_change) then
if rng.percent(self.data.tunnel_random) then
xdir, ydir = self:randDir()
else
xdir, ydir = self:tunnelDir(x1, y1, x2, y2)
end
end
local nx, ny = x1 + xdir, y1 + ydir
while true do
if self.map:isBound(nx, ny) and (self.room_map[nx][ny].room or not self.room_map[nx][ny].tunnel) then break end
if rng.percent(self.data.tunnel_random) then
xdir, ydir = self:randDir()
else
xdir, ydir = self:tunnelDir(x1, y1, x2, y2)
end
nx, ny = x1 + xdir, y1 + ydir
end
if self.room_map[nx][ny].room and not self.room_map[nx][ny].can_open then
else
for i = -1, 1 do for j = -1, 1 do
if self.map:isBound(nx + i, ny + j) then
self.room_map[nx + i][ny + j].can_open = false
end
end end
tun[#tun+1] = {nx,ny}
end
x1, y1 = nx, ny
if x1 == x2 and y1 == y2 then break end
tries = tries - 1
end
for _, t in ipairs(tun) do
local nx, ny = t[1], t[2]
-- self.room_map[nx][ny].tunnel = true
self.map(nx, ny, Map.TERRAIN, self.grid_list[self:resolve("<")])
end
end
function _M:generate()
for i = 0, self.map.w - 1 do for j = 0, self.map.h - 1 do
self.map(i, j, Map.TERRAIN, self.grid_list[self:resolve("#")])
end end
local nb_room = 10
local rooms = {}
while nb_room > 0 do
local r = self:roomAlloc(self.rooms[rng.range(1, #self.rooms)], #rooms+1)
if r then rooms[#rooms+1] = r end
nb_room = nb_room - 1
end
-- Tunnels !
print("Begin tunnel", #rooms, rooms[1])
local tx, ty = rooms[1].cx, rooms[1].cy
for i = 2, #rooms do
self:tunnel(tx, ty, rooms[i].cx, rooms[i].cy)
tx, ty = rooms[i].cx, rooms[i].cy
end
-- Always starts at 1, 1
self.map(1, 1, Map.TERRAIN, self.up)
return 1, 1
end
......@@ -8,6 +8,7 @@ function _M:init(map, grid_list, data)
self.data = data
self.grid_list = grid_list
self.tiles, self.raw = self:loadTiles(data.tileset)
self.matching_tiles = {}
self.block = self.raw.base
self.cols = math.floor(self.map.w / self.block.w)
......@@ -96,25 +97,69 @@ function _M:matchTile(t1, t2)
end
function _M:findMatchingTiles(st, dir)
if self.matching_tiles[st] and self.matching_tiles[st][dir] then return self.matching_tiles[st][dir] end
local m = {}
for _, dt in ipairs(self.tiles) do
local ok = true
print("try match ", st.id, dt.id)
if dir == 8 then
for i = 1, self.block.w do
if not self:matchTile(st[i][1], dt[i][self.block.h]) then ok = false end
local sw = #st
local dw = #dt
print("sw/dw", sw,dw,#st[1],#dt[1])
if dw < sw then
print("dest 8 smaller")
for offset = 0, sw - dw do
ok = true
for i = 1, dw do
print("","try offset",offset,i,"::",st[i+offset] and st[i+offset][1], dt[i] and dt[i][self.block.h])
if not st[i+offset] or not dt[i] or not self:matchTile(st[i+offset][1], dt[i][self.block.h]) then ok = false end
end
print("tried ",offset,"result",ok)
if ok then break end
end
else
print("dest 8 bigger")
for offset = 0, dw - sw do
ok = true
for i = 1, sw do
print("","try offset",offset,i,"::",st[i] and st[i][1], dt[i+offset] and dt[i+offset][self.block.h])
if not st[i] or not dt[i+offset] or not self:matchTile(st[i][1], dt[i+offset][self.block.h]) then ok = false end
end
print("tried ",offset,"result",ok)
if ok then break end
end
end
elseif dir == 2 then
for i = 1, self.block.w do
if not self:matchTile(st[i][self.block.h], dt[i][1]) then ok = false end
--[[
local sw = #st
local dw = #dt
if dw < sw then
print("dest 2 smaller")
for offset = 0, sw - dw do
for i = offset + 1, offset + dw do
if not st[i] or not dt[i] or not self:matchTile(st[i][self.block.h], dt[i][1]) then ok = false end
end
print("tried ",offset,"result",ok)
end
else
print("dest 2 bigger")
for offset = 0, dw - sw do
for i = offset + 1, offset + sw do
if not self:matchTile(st[i][self.block.h], dt[i][1]) then ok = false end
end
print("tried ",offset,"result",ok)
end
end
]]
elseif dir == 4 then
for j = 1, self.block.h do
if not self:matchTile(st[1][j], dt[self.block.w][j]) then ok = false end
if not self:matchTile(st[1][j], dt[#dt][j]) then ok = false end
end
elseif dir == 6 then
for j = 1, self.block.h do
if not self:matchTile(st[self.block.w][j], dt[1][j]) then ok = false end
if not self:matchTile(st[#dt][j], dt[1][j]) then ok = false end
end
end
if ok then
......@@ -123,6 +168,9 @@ function _M:findMatchingTiles(st, dir)
end
end
self.matching_tiles[st] = self.matching_tiles[st] or {}
self.matching_tiles[st][dir] = m
return m
end
......@@ -142,8 +190,9 @@ function _M:buildTile(tile, bx, by, rid)
if not self:roomAlloc(bx, by, bw, bh, rid) then return false end
for i = 1, self.block.w do
for j = 1, self.block.h do
print("building tile", tile.id, #tile, #tile[1])
for i = 1, #tile do
for j = 1, #tile[1] do
self.map(bx * self.block.w + i - 1, by * self.block.h + j - 1, Map.TERRAIN, self.grid_list[self:resolve(tile[i][j])])
end
end
......@@ -152,8 +201,10 @@ function _M:buildTile(tile, bx, by, rid)
local coord = dir_to_coord[o[3]]
local mts = self:findMatchingTiles(tile, o[3])
opens[#opens+1] = {bx + coord[1], by + coord[2], tile=mts[rng.range(1, #mts)]}
print("room at ",bx,by,"opens to",o[3],"::",bx + coord[1], by + coord[2])
if #mts > 0 then
opens[#opens+1] = {bx + coord[1], by + coord[2], tile=mts[rng.range(1, #mts)]}
print("room at ",bx,by,"opens to",o[3],"::",bx + coord[1], by + coord[2])
end
end
return opens
......@@ -167,7 +218,7 @@ function _M:generate()
local first = true
local process = {}
local id = 1
process[#process+1] = {math.floor(self.cols / 2), math.floor(self.rows / 2), tile=self.tiles[rng.range(1, #self.tiles)]}
process[#process+1] = {math.floor(self.cols / 2), math.floor(self.rows / 2), tile=self.tiles[2 or rng.range(1, #self.tiles)]}
while #process > 0 do
local b = table.remove(process)
local type = "room"
......
return {
[[#!!!!!!!!#]],
[[!........!]],
[[!...##...!]],
[[!........!]],
[[#!!!!!!!!#]],
}
return {
[[#!!!!!!!!!!#]],
[[!..........!]],
[[!..........!]],
[[!..........!]],
[[!..........!]],
[[!..........!]],
[[#!!!!!!!!!!#]],
}
......@@ -8,24 +8,16 @@ matcher = function(t1, t2)
end
tiles =
{type="tunnel",
{
[[#####]],
[[#####]],
[[.....]],
[[#####]],
[[#####]],
},
{type="tunnel",
[[##.##]],
[[##.##]],
[[##.##]],
[[##.##]],
[[##.##]],
[[#.#]],
[[#.#]],
[[#<#]],
[[#.#]],
[[#.#]],
},
{type="tunnel",
[[##.##]],
[[##.##]],
......@@ -34,6 +26,14 @@ tiles =
[[##.##]],
},
--[=[
{type="tunnel",
{
[[#####]],
[[.....]],
[[#####]],
},
{type="tunnel",
[[##.##]],
[[##.##]],
......@@ -65,7 +65,8 @@ tiles =
[[##.##]],
[[##.##]],
},
]=]
--[=[
{type="tunnel",
[[##.##]],
[[##.##]],
......@@ -157,7 +158,7 @@ tiles =
[[....#]],
[[#####]],
},
]=]
--[=[
{type="room",
......
......@@ -2,16 +2,17 @@ return {
name = "ancient ruins",
level_range = {1, 5},
max_level = 5,
width = 50, height = 30,
width = 100, height = 100,
all_remembered = true,
all_lited = true,
-- persistant = true,
generator = {
map = {
class = "engine.generator.map.TileSet",
tileset = "dungeon",
class = "engine.generator.map.Roomer",
rooms = {"simple","pilar"},
['.'] = "FLOOR",
['#'] = "WALL",
['<'] = "UP",
up = "UP",
down = "DOWN",
['+'] = "DOOR",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment