Just another update

This commit is contained in:
Ingy döt Net 2015-02-20 00:35:01 -05:00
parent a25938f123
commit 00a190b0a6
6591 changed files with 94363 additions and 23227 deletions

View file

@ -1,4 +1,4 @@
void main() {
void main() @safe {
import std.stdio, std.algorithm, std.range, std.random;
enum uint w = 14, h = 10;
@ -6,9 +6,10 @@ void main() {
hor = iota(h + 1).map!(_ => ["+---"].replicate(w)).array,
ver = h.iota.map!(_ => ["| "].replicate(w) ~ "|").array;
void walk(in uint x, in uint y) /*nothrow*/ {
void walk(in uint x, in uint y) /*nothrow*/ @safe /*@nogc*/ {
vis[y][x] = true;
foreach (p; [[x-1,y], [x,y+1], [x+1,y], [x,y-1]].randomCover) {
//foreach (immutable p; [[x-1,y], [x,y+1], [x+1,y], [x,y-1]].randomCover) {
foreach (const p; [[x-1, y], [x, y+1], [x+1, y], [x, y-1]].randomCover) {
if (p[0] >= w || p[1] >= h || vis[p[1]][p[0]]) continue;
if (p[0] == x) hor[max(y, p[1])][x] = "+ ";
if (p[1] == y) ver[y][max(x, p[0])] = " ";
@ -17,5 +18,5 @@ void main() {
}
walk(uniform(0, w), uniform(0, h));
foreach (const a, const b; hor.zip(ver ~ []))
join(a ~ ["+\n"] ~ b).writeln;
join(a ~ "+\n" ~ b).writeln;
}

View file

@ -0,0 +1,17 @@
Stack = {}
function Stack:Create()
local stack = {}
function stack:push(item)
self[#self + 1] = item
end
function stack:pop()
local item = self[#self]
self[#self] = nil
return item
end
return stack
end

View file

@ -0,0 +1,114 @@
require "stack"
Maze =
{
directions =
{
north = { x = 0, y = -1 },
east = { x = 1, y = 0 },
south = { x = 0, y = 1 },
west = { x = -1, y = 0 }
}
}
function Maze:Create(width, height, closed)
-- Actual maze setup
local maze = {}
for y = 1, height do
maze[y] = {}
for x = 1, width do
maze[y][x] = { east = self:CreateDoor(closed), south = self:CreateDoor(closed)}
-- Doors are shared beetween the cells to avoid out of sync conditions and data dublication
if x ~= 1 then maze[y][x].west = maze[y][x - 1].east
else maze[y][x].west = self:CreateDoor(closed) end
if y ~= 1 then maze[y][x].north = maze[y - 1][x].south
else maze[y][x].north = self:CreateDoor(closed) end
end
end
function maze:resetDoors(close)
for y = 1, #self do
self[y][#self[1]].east:setOpened(not close)
for i, cell in ipairs(self[y]) do
cell.north:setOpened(not close)
cell.west:setOpened(not close)
end
end
for i, cell in ipairs(self[#self]) do
cell.south:setOpened(not close)
end
end
function maze:resetVisited()
for y = 1, #self do
for x = 1, #self[1] do
self[y][x].visited = nil
end
end
end
function maze:tostring(wall, passage)
wall = wall or "#"
passage = passage or " "
local result = ""
local verticalBorder = ""
for i = 1, #self[1] do
verticalBorder = verticalBorder .. wall .. (self[1][i].north:isClosed() and wall or passage)
end
verticalBorder = verticalBorder .. wall
result = result .. verticalBorder .. "\n"
for y, row in ipairs(self) do
local line = row[1].west:isClosed() and wall or passage
local underline = wall
for x, cell in ipairs(row) do
line = line .. " " .. (cell.east:isClosed() and wall or passage)
underline = underline .. (cell.south:isClosed() and wall or passage) .. wall
end
result = result .. line .. "\n" .. underline .. "\n"
end
return result
end
return maze
end
-- This function was designed to be easily replaced by the function generating Legend of Grimrock doors
function Maze:CreateDoor(closed)
local door = {}
door._closed = closed and true or false
function door:isClosed()
return self._closed
end
function door:isOpened()
return not self._closed
end
function door:close()
self._closed = true
end
function door:open()
self._closed = false
end
function door:setOpened(opened)
if opened then
self:open()
else
self:close()
end
end
return door
end

View file

@ -0,0 +1,41 @@
require "maze"
-- Backtracker algorithm (a variation of the recursive backtracker algorithm made without recursion)
function Maze:Backtracker(maze)
maze:resetDoors(true)
local stack = Stack:Create()
local cell = { x = 1, y = 1 }
while true do
maze[cell.y][cell.x].visited = true
-- Gathering all possible travel direction in a list
local directions = {}
for key, value in pairs(self.directions) do
local newPos = { x = cell.x + value.x, y = cell.y + value.y }
-- Checking if the targeted cell is in bounds and was not visited previously
if maze[newPos.y] and maze[newPos.y][newPos.x] and not maze[newPos.y][newPos.x].visited then
directions[#directions + 1] = { name = key, pos = newPos }
end
end
-- If there are no possible travel directions - backtracking
if #directions == 0 then
if #stack > 0 then
cell = stack:pop()
goto countinue
else break end -- Stack is empty and there are no possible directions - maze is generated
end
-- Choosing a random direction from a list of possible direction and carving
stack:push(cell)
local dir = directions[math.random(#directions)]
maze[cell.y][cell.x][dir.name]:open()
cell = dir.pos
::countinue::
end
maze:resetVisited()
end

View file

@ -0,0 +1,9 @@
require "maze"
require "backtracker"
maze = Maze:Create(30, 10, true)
--[[ Maze generation depends on the random seed, so you will get exactly
identical maze every time you pass exactly identical seed ]]
math.randomseed(os.time())
Maze:Backtracker(maze)
print(maze:tostring())