diff --git a/game/engine/generator/map/Roomer.lua b/game/engine/generator/map/Roomer.lua new file mode 100644 index 0000000000000000000000000000000000000000..9530aee1f654ead61d8986969d0afb49060c0bdd --- /dev/null +++ b/game/engine/generator/map/Roomer.lua @@ -0,0 +1,195 @@ +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 diff --git a/game/engine/generator/map/TileSet.lua b/game/engine/generator/map/TileSet.lua index 086c55d7a0326fe08b5ae90c8b09d0f039c1caa5..2a6a2cac46e9cc28b54e000ab4de008548ff3568 100644 --- a/game/engine/generator/map/TileSet.lua +++ b/game/engine/generator/map/TileSet.lua @@ -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" diff --git a/game/modules/tome/data/rooms/pilar.lua b/game/modules/tome/data/rooms/pilar.lua new file mode 100644 index 0000000000000000000000000000000000000000..410293a4100024a259d02cee63fc97d36d132796 --- /dev/null +++ b/game/modules/tome/data/rooms/pilar.lua @@ -0,0 +1,7 @@ +return { +[[#!!!!!!!!#]], +[[!........!]], +[[!...##...!]], +[[!........!]], +[[#!!!!!!!!#]], +} diff --git a/game/modules/tome/data/rooms/simple.lua b/game/modules/tome/data/rooms/simple.lua new file mode 100644 index 0000000000000000000000000000000000000000..fc78931335db48bf7c13f0028360fc50698dfc2b --- /dev/null +++ b/game/modules/tome/data/rooms/simple.lua @@ -0,0 +1,9 @@ +return { +[[#!!!!!!!!!!#]], +[[!..........!]], +[[!..........!]], +[[!..........!]], +[[!..........!]], +[[!..........!]], +[[#!!!!!!!!!!#]], +} diff --git a/game/modules/tome/data/tilesets/dungeon.lua b/game/modules/tome/data/tilesets/dungeon.lua index 04815cf92d1e97784812e77bd53cbf9bbf6f4ea0..ceb647b429774aa0be46699971626a54d369c2e2 100644 --- a/game/modules/tome/data/tilesets/dungeon.lua +++ b/game/modules/tome/data/tilesets/dungeon.lua @@ -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", diff --git a/game/modules/tome/data/zones/ancient_ruins/zone.lua b/game/modules/tome/data/zones/ancient_ruins/zone.lua index a13e028da842791bb1f7349cad50768a77caccb2..13c29e2b696979dd4ba928617c62e8ebd06d697b 100644 --- a/game/modules/tome/data/zones/ancient_ruins/zone.lua +++ b/game/modules/tome/data/zones/ancient_ruins/zone.lua @@ -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",