Perfect Maze now working

After a thorough going over of the code, I’ve managed to get this one working. Although painfully slow, at least it works. In the future I will be looking at other algorithms which are much faster. I only remembered this one from a long time ago so I just thought I’d have a go on my own without any help with implementing it.

// File: generate.agc
// Created: 19-09-21

/*
	Attempting to generate a maze using a decent algorithm.
	Unfortunately this particular algorith is painfully slow,
	but for the time being, it does work.
*/

type MAZE
	seed as integer
	wid as integer
	hgt as integer
	maze as integer[0,0]
endtype

function maze_get_odd_random(max as integer)
	val = random(0, ((max - 2) / 2)) * 2 + 1
endfunction val

function maze_not_visited(obj ref as MAZE, xpos, ypos)
	val = obj.maze[ypos, xpos]
endfunction val

/*
	The width and height have to be even numbers.
	NB: In AGK this means 0 to width (as even) for example
		NOT 0 to width - 1
*/

function maze_gen(obj ref as MAZE, wid as integer, hgt as integer, seed as integer)
	obj.seed = seed
	
	SetRandomSeed(seed)
	
	obj.wid = wid
	obj.hgt = hgt

	/*
		Wierd way of assigning a multidimensional array
		Assign the first dimensions length
		And then assign the length of each separate part
		ie.
		a[0].length = 5 (giving a[0,4])
		is not the same as
		a[1].length = 10 (which gives a[1,9])
		
		Also, AGK arrays end with the value assigned.
		ie. length is 10 so the array goes from 0 to 10
		instead of 0 to 9.
	*/
	
	obj.maze.length = hgt

	for c = 0 to hgt
		obj.maze[c].length = wid
		
		for x = 0 to wid
			obj.maze[c, x] = 1
		next
	next c
	
	/*
		If I remember correctly, I choose a random cell.
		But, it has to be, erm, ODD or EVEN???
		I will find out...
		
		It has to be odd.
	*/
	
	currentx = maze_get_odd_random(wid)
	currenty = maze_get_odd_random(hgt)
	
	// set position to 0
	
	obj.maze[currenty, currentx] = 0
	
	done = 0
	
	repeat
		
		// iterations to run through (might increase)
		for route = 0 to 63
			
			/*
				Basically direction is UP, DOWN, LEFT or RIGHT
			*/
			
			direction = random(0, 3)
			
			select direction
				case 0:
					if currenty - 2 > 0
						if maze_not_visited(obj, currentx, currenty - 2)
							obj.maze[currenty - 2, currentx] = 0 // clear path
							obj.maze[currenty - 1, currentx] = 0 // between
						endif
						dec currenty, 2
					endif
				endcase
				
				case 1:
					if currenty + 2 < hgt
						if maze_not_visited(obj, currentx, currenty + 2)
							obj.maze[currenty + 2, currentx] = 0
							obj.maze[currenty + 1, currentx] = 0
						endif
						inc currenty, 2
					endif
				endcase
				
				case 2:
					if currentx - 2 > 0
						if maze_not_visited(obj, currentx - 2, currenty)
							obj.maze[currenty, currentx - 2] = 0
							obj.maze[currenty, currentx - 1] = 0
						endif
						dec currentx, 2
					endif
				endcase
				
				case 3:
					if currentx + 2 < wid
						if maze_not_visited(obj, currentx + 2, currenty)
							obj.maze[currenty, currentx + 2] = 0
							obj.maze[currenty, currentx + 1] = 0
						endif
						inc currentx, 2
					endif
				endcase
			endselect
		next
		
		/*
			Print this mazes iteration (just for testing)
		*/
		
		Print( ScreenFPS() )
		maze_print(obj)
		print("Calculating...")
		sync()
		
		/*
			Check if maze is done (the silly bit)
		*/
		
		done = 0
		
		for h = 1 to hgt - 1 step 2
			for w = 1 to wid - 1 step 2
				if obj.maze[h, w] = 1
					done = 1
					exit // quick exit if not done
				endif
			next
			if done = 1 then exit
		next
		
	until done = 0
	
endfunction obj

function maze_print(obj ref as MAZE)
	print (obj.wid)
	print (obj.hgt)
	//print (random(0, 2) - 1) // HUH
	
	for h = 0 to obj.hgt
		s as string = ""
		for w = 0 to obj.wid
			if obj.maze[h, w] = 1 then s = s + "#" else s = s + " "
		next
		print (s)
	next
endfunction

Hmm… Almost…

// File: generate.agc
// Created: 19-09-21

/*
	Attempting to generate a maze using a decent algorithm
*/

type MAZE
	seed as integer
	wid as integer
	hgt as integer
	maze as integer[0,0]
endtype

function maze_get_odd_random(max as integer)
	val = random(0, max / 2) + 1
endfunction val

function maze_not_visited(obj as MAZE, xpos, ypos)
	val = obj.maze[ypos, xpos]
endfunction val

/*
	The width and height have to be even numbers.
	NB: In AGK this means 0 to width (as even) for example
		NOT 0 to width - 1
*/

function maze_gen(obj ref as MAZE, wid as integer, hgt as integer, seed as integer)
	obj.seed = seed
	
	//SetRandomSeed(seed)
	
	obj.wid = wid
	obj.hgt = hgt

	/*
		Wierd way of assigning a multidimensional array
		Assign the first dimensions length
		And then assign the length of each separate part
		ie.
		a[0].length = 5 (giving a[0,4])
		is not the same as
		a[1].length = 10 (which gives a[1,9])
		
		Also, AGK arrays end with the value assigned.
		ie. length is 10 so the array goes from 0 to 10
		instead of 0 to 9.
	*/
	
	obj.maze.length = hgt

	for c = 0 to hgt
		obj.maze[c].length = wid
		
		for x = 0 to wid
			obj.maze[c, x] = 1
		next
	next c
	
	/*
		If I remember correctly, I choose a random cell.
		But, it has to be, erm, ODD or EVEN???
		I will find out...
		
		It has to be odd.
	*/
	
	currentx = maze_get_odd_random(wid)
	currenty = maze_get_odd_random(hgt)
	
	// set position to 0
	
	obj.maze[currenty, currentx] = 0
	
	done = 0
	
	repeat
		
		// iterations to run through (might increase)
		for route = 0 to 3
			
			/*
				Basically direction is UP, DOWN, LEFT or RIGHT
			*/
			
			direction = random(0, 3)
			
			select direction
				case 0:
					if maze_not_visited(obj, currentx, currenty - 2) and currenty - 2 > 0
						obj.maze[currenty - 2, currentx] = 0 // clear path
						obj.maze[currenty - 1, currentx] = 0 // between
						currenty = currenty - 2
					endif
				endcase
				
				case 1:
					if maze_not_visited(obj, currentx, currenty + 2) and currenty +2 < hgt
						obj.maze[currenty + 2, currentx] = 0
						obj.maze[currenty + 1, currentx] = 0
						currenty = currenty + 2
					endif
				endcase
				
				case 2:
					if maze_not_visited(obj, currentx - 2, currenty) and currentx - 2 > 0
						obj.maze[currenty - 2, currentx] = 0
						obj.maze[currenty - 1, currentx] = 0
						currentx = currentx - 2
					endif
				endcase
				
				case 3:
					if maze_not_visited(obj, currentx + 2, currenty) and currentx + 2 < wid
						obj.maze[currenty, currentx + 2] = 0
						obj.maze[currenty, currentx + 1] = 0
						currentx = currentx + 2
					endif
				endcase
			endselect
		next
		
		/*
			Check if maze is done (the silly bit)
		*/
		
		for h = 1 to hgt - 1 step 2
			for w = 1 to wid - 1 step 2
				if obj.maze[h, w] = 1
					done = 1
					exit // quick exit if not done
				endif
			next
			if done = 1 then exit
		next
		
	until done = 0
	
endfunction obj

function maze_print(obj ref as MAZE)
	print (obj.wid)
	print (obj.hgt)
	print (random(0, 2) - 1) // HUH
	
	for h = 0 to obj.hgt
		s as string = ""
		for w = 0 to obj.wid
			if obj.maze[h, w] = 1 then s = s + "#" else s = s + " "
		next
		print (s)
	next
endfunction

Not quite working… Need a nap… Not well…

A Perfect Maze

So I got an algorithm done last week that produced a perfect maze. Unfortunately though, I wiped my 2 x 1Tb SSD’s on my PC and didn’t back up the code.

So I am starting again.

(I’m not too good by the way, so I am documenting this)

I didn’t want a recursive algorithm because I think that on low end architecture this would be bad for memory usage. This meant that the algorithm would possibly be slower. For a 40 by 40 maze it would still be instant, even though there was a silly check in there.

Here goes. (back soon with some snippets)

I’m using AGK and will port everything to C.