Source: SoupGraph.makeMaze.js

if (typeof SoupGraph != "function") {
	console.error("SoupGraph is not defined. Cannot attach a function to an undefined object!");
} else if (typeof SoupGraph.prototype.makeMaze != "undefined") {
	console.error("Cannot attach the makeMaze function to SoupGraph because it is already defined!");
} else {
	/**
	 * Turns a SoupGraph into a maze. Please note that if the graph has unidirectional edges or disconnected graphs, the maze may become unsolvable
	 */
	SoupGraph.prototype.makeMaze = function() {
		// Get IDs of all nodes in the graph
		var nodeIds = this.nodes;

		// Turn the graph into a maze
		(function generateMaze(self) {
			// Start the generation with a random node
			var nodesToProcess = [
				{
					node: nodeIds[Math.floor(Math.random()*nodeIds.length)],
					entryEdge: null
				}
			];
			var processed = {};

			// Generate!
			while (nodesToProcess.length > 0) {
				// Pop a node to process
				var processing = nodesToProcess.pop();
				var entryEdge = processing.entryEdge;
				var processing = processing.node;

				// Has self cell been processed already?
				if (typeof processed[processing] != "undefined")
					continue;
				// Mark self node as processed
				processed[processing] = true;

				// Find all neighbours
				var edges = self.getEdgesFrom(processing);
				var neighbours = {};
				edges.forEach(function(edge) {
					neighbours[edge.name] = edge
				});
				// Randomly add the neighbours to the stack
				for (var i = 0; i < edges.length; i++) {
					// Pick a random direction
					var edgeName = (function() {
						var result;
						var count = 0;
						for (var edgeName in neighbours) {
							if (Math.random() < 1/++count)
								result = edgeName;
						}
						return result;
					})();

					// Get the randomly chosen edge
					var edge = neighbours[edgeName];
					// Get the node in that edgeName
					var nextNode = edge.toNode;
					// Remove the node from the neighbours list so it is not picked again
					delete neighbours[edgeName];
					// Check if the neighbour has been processed
					if (typeof processed[nextNode] != "undefined") {
						// Get all edges in the opposite direction
						var reverseEdges = self.getEdges(nextNode, processing);
						if (reverseEdges.indexOf(entryEdge) >= 0)
							continue;
						self.removeEdge(edge);
						reverseEdges.forEach(function(reverseEdge) {
							self.removeEdge(reverseEdge);
						});
					} else {
						// Push the neighbour onto the stack
						nodesToProcess.push({node: nextNode, entryEdge: edge});
					}
				}
			}
		})(this);

		// The graph is now a maze. Return this
		return this;
	};
}