RoboCatz.com
About FLL | Navigation | Playbook | Strategy | Models | Techniques | RobotC | Programming | Robot News |

-- Maze Generator Module Script for Roblox

-- Maze Generator Module Script for Roblox
--[[
Updated: 5/19/2023

This is the script to generate mazes.  This script needs to be placed in the ReplicatedStorage folder.  The name must be: mazeGenerator

mazeGenerator ModuleScript to be stored in the ReplicatedStorage

Example usage:

m.newMaze({numRows=10, numCols=10, cellWidth=20, cellLength=20, withNumbers=false, withColors=true, wallThickness=3, height=3})



]]

local Amazing = {}
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local s = require(ReplicatedStorage.genericShapes)

local withNumbers = false
local withColors = false
local openDoor = 0
local Arr = {}
local levelDivisionOffset = {2,1,0}
local colors = {'white','red','green','blue','yellow','purple','black'}

local totalLoops = 200
math.randomseed(tick())
function randomIntFromInterval(min, max) -- min and max included
	local retVal = Random.new():NextInteger(min, max)
	--local retVal = math.floor(math.random() * ((max - min) - 1) + min)
	--print(`Random range: {min} {max}; Returning: {retVal}`)
	return retVal
end

function divide(minCol, maxCol, minRow, maxRow, level, quadrant)
	if level > 5 then return end
	totalLoops -= 1
	if totalLoops < 0 then return end
	print(`Quadrant: {quadrant}; Level: {level}; Divider is: {colors[level]}; Area is: c1={minCol}, c2={maxCol}, r1={minRow}, r2={maxRow}`)
	if maxCol-minCol<2 or maxRow-minRow<2 then
		if maxCol-minCol<2 then print(`This quadrant {quadrant} does not have required column size {minCol} and {maxCol}`) end
		if maxRow-minRow<2 then print(`This quadrant {quadrant} does not have required row size {minRow} and {maxRow}`) end
		return
	end
	local offset = (levelDivisionOffset[level] and levelDivisionOffset[level] or 0)

	print(`Getting a random column between {minCol} and {maxCol}`)
	local col = randomIntFromInterval(minCol+1+offset, (maxCol-1)-offset)
	print(`My column is: {col} is between {minCol} and {maxCol}`)
	for i=minRow, maxRow do	Arr[i][col].vertical=level end

	print(`Getting a random row between {minRow} and {maxRow}`)
	local row = randomIntFromInterval(minRow+1+offset, (maxRow-1)-offset)
	print(`My row is: {row} is between {minRow} and {maxRow}`)
	for j=minCol, maxCol do	Arr[row][j].horizontal=level end
	print(`I just set the columns in row {row} from Column: {minCol} to {maxCol}`)

	-- open some doors
	local door = randomIntFromInterval(minCol, col)
	--print(`Door at: {door} - horizontal`)
	Arr[row][door].horizontal=openDoor
	door = randomIntFromInterval(col+1, maxCol)
	if(door > #Arr[row]) then door = #Arr[row] end
	--print(`Door at: {door} - horizontal`)
	Arr[row][door].horizontal=openDoor  
	door = randomIntFromInterval(minRow, row)
	--print(`Door at: {door} - vertical`)
	Arr[door][col].vertical=openDoor
	door = randomIntFromInterval(row+1, maxRow)
	--print(`Door at: {door} - vertical`)
	if(door > #Arr) then door = #Arr end
	Arr[door][col].vertical=openDoor  


	-- Draw a text number at the intersection of row and col
	if withNumbers then
		--local t1 = text(col*colWidth-(numCols*colWidth/2), row*rowHeight, 0, ''+level, 20, 'black', 'Arial Black')
		--if (withColors) t1.fill(colors[level])
	end
	-- Do the recursion here for all four quadrants
	print(`About to divide now. Quadrant is {quadrant}; Current level={level}`)

	print(`Division 1: minCol={minCol}, col={col}, minRow={minRow}, row={row}, level+1={level+1}`)
	divide(minCol, col, minRow, row, level+1, "Quadrant1")

	print(`Division 2: minCol={minCol}, col={col}, row={row}, maxRow={maxRow}, level+1={level+1}`)
	divide(minCol, col, row+1, maxRow, level+1, 'Quadrant2')

	print(`Division 3: col={col}, maxCol={maxCol}, minRow={minRow}, row={row}, level+1={level+1}`)
	divide(col+1, maxCol, minRow, row, level+1, 'Quadrant3')

	print(`Division 4: col={col}, maxCol={maxCol}, row={row}, maxRow={maxRow}, level+1={level+1}`)
	divide(col+1, maxCol, row+1, maxRow, level+1, 'Quadrant4')
end

function Amazing.newMaze(mazeParms)
	if typeof(mazeParms) ~= "table" then
		print("No maze generated.  You need to pass a table to the function newMaze().")
		return
	end
	print("Working on the maze")
	local numRows = mazeParms.numRows
	local numCols = mazeParms.numCols
	local rowHeight = mazeParms.cellLength
	local colWidth = mazeParms.cellWidth
	withNumbers = mazeParms.withNumbers  -- global variable to this module
	withColors = mazeParms.withColors    -- global variable to this module

	local colors = {'white','red','green','blue','yellow','purple','black'}
	local r1=s.rectangle(0,numRows*rowHeight/2, numCols*colWidth-(numCols*colWidth/2), numRows*rowHeight)
	s.moveTo(r1, 0, 0, 0)
	s.rotateBy(r1, 90, 0, 0)
	for i = 1, numRows do
		Arr[i] = {}
		for j = 1, numCols do
			Arr[i][j] = {vertical=0, horizontal=0 }
		end
	end
	divide(1, numCols, 1, numRows, 1, 'All')
	-- Render
	for i=1, numRows do
		for j=1, numCols do
			local z = (((rowHeight+mazeParms.wallThickness) * (i-1/2)) - (numRows*(rowHeight+mazeParms.wallThickness)/2)) - rowHeight*0.1
			local x = (((colWidth+mazeParms.wallThickness)  * (j-1)) - (numCols*(colWidth+mazeParms.wallThickness)/2)) + colWidth*0.07
			print(`Maze Row {i}  Col {j}`)
			if Arr[i][j].horizontal>0 then
				local wallPart = s.wall( Vector3.new(x, 0, z+rowHeight+mazeParms.wallThickness), Vector3.new(x+colWidth, mazeParms.height, z+rowHeight+mazeParms.wallThickness), mazeParms.wallThickness, (withColors and colors[Arr[i][j].horizontal] or nil) )  --  
				--s.cube(x,2,z,1,"red")
				--s.cube(x-(colWidth-1),2,z,1,"green")
			else
				--local wallPart = s.wall( Vector3.new(x-colWidth/2-colWidth/4, 0, z), Vector3.new(x-colWidth/2-(colWidth*0.75), mazeParms.height, z), mazeParms.wallThickness, (withColors and Color3.new(0, 0.333333, 0.498039) or nil) )  --  
			end
			if Arr[i][j].vertical>0 then
				local wallPart = s.wall( Vector3.new(x+colWidth, 0, z), Vector3.new(x+colWidth, mazeParms.height, z+rowHeight), mazeParms.wallThickness, (withColors and colors[Arr[i][j].vertical] or nil) )
			else
				--local wallPart = s.wall( Vector3.new(x, 0, z-rowHeight/2-rowHeight/4), Vector3.new(x, mazeParms.height, z-rowHeight/2-(rowHeight*0.75)), mazeParms.wallThickness, (withColors and colors[Arr[i][j].vertical] or nil) )
			end
		end
	end
end


return Amazing