UNPKG

generate-maze

Version:

Maze generator using a JavaScript implementation of Eller's Algorithm, as described here: http://www.neocomputer.org/projects/eller.html

1 lines 7.57 kB
{"version":3,"file":"generate-maze.cjs","sources":["../src/generate-maze.ts"],"sourcesContent":["type Cell = {\n x: number,\n y: number,\n top: boolean,\n left: boolean,\n bottom: boolean,\n right: boolean,\n set: number,\n}\n\nfunction compact<T>(array: T[]): T[] {\n return array.filter(Boolean);\n}\nfunction difference<T>(c: T[], d: T[]): T[] {\n return [c, d].reduce((a, b) => a.filter(c => !b.includes(c)));\n}\nfunction initial<T>(array: T[]): T[] {\n return array.slice(0, -1);\n}\nfunction groupBy<T>(list: T[], key: string): { [key: string]: T[] } {\n const keys = list.map(item => item[key]);\n let dict = uniq(keys).reduce((prev, next) => {\n return {\n ...prev,\n [next]: []\n }\n }, {});\n\n list.forEach(item => dict[item[key]].push(item));\n\n return dict;\n}\nfunction last<T>(array: T[]): T {\n return array[array.length - 1];\n}\nfunction range(n: number, end = 0): number[] {\n return end ? Array.from(Array(end - n).keys()).map(k => k + n) : Array.from(Array(n).keys());\n}\nfunction uniq<T>(array: T[]): T[] {\n return [...new Set(array)];\n}\nfunction sampleSize<T>(array: T[], n: number, random: () => number) {\n n = n == null ? 1 : n;\n const length = array == null ? 0 : array.length;\n if (!length || n < 1) {\n return [];\n }\n n = n > length ? length : n;\n let index = -1;\n const lastIndex = length - 1;\n const result = [...array];\n while (++index < n) {\n const rand = index + Math.floor(random() * (lastIndex - index + 1));\n const value = result[rand];\n result[rand] = result[index];\n result[index] = value;\n }\n return result.slice(0, n);\n}\n\nfunction mulberry32(seed: number) {\n return function () {\n let t = seed += 0x6D2B79F5;\n t = Math.imul(t ^ t >>> 15, t | 1);\n t ^= t + Math.imul(t ^ t >>> 7, t | 61);\n return ((t ^ t >>> 14) >>> 0) / 4294967296;\n }\n}\n\nfunction mergeSetWith(row: Cell[], oldSet: number, newSet: number) {\n row.forEach(box => {\n if (box.set === oldSet) box.set = newSet;\n });\n}\n\nfunction populateMissingSets(row: Cell[], random: () => number) {\n const setsInUse = compact(uniq(row.map(row => row.set)));\n const allSets = range(1, row.length + 1);\n const availableSets = difference(allSets, setsInUse).sort(() => 0.5 - random());\n row.filter(box => !box.set).forEach((box, i) => box.set = availableSets[i]);\n}\n\nfunction mergeRandomSetsIn(row: Cell[], random: () => number, probability = 0.5) {\n // Randomly merge some disjoint sets\n const allBoxesButLast = initial(row);\n allBoxesButLast.forEach((current, x) => {\n const next = row[x + 1];\n const differentSets = current.set !== next.set;\n const shouldMerge = random() <= probability;\n if (differentSets && shouldMerge) {\n mergeSetWith(row, next.set, current.set);\n current.right = false;\n next.left = false;\n }\n });\n}\n\nfunction addSetExits(row: Cell[], nextRow: Cell[], random: () => number) {\n // Randomly add bottom exit for each set\n const setsInRow = Object.values(groupBy(row, 'set'));\n const { ceil } = Math;\n setsInRow.forEach(set => {\n const exits = sampleSize(set, ceil(random() * set.length), random);\n exits.forEach(exit => {\n if (exit) {\n const below = nextRow[exit.x];\n exit.bottom = false;\n below.top = false;\n below.set = exit.set;\n }\n });\n });\n}\n\nfunction generate(width = 8, height = width, closed = true, seed = 1) {\n const random = mulberry32(seed);\n const maze = [];\n const r = range(width);\n\n // Populate maze with empty cells:\n for (let y = 0; y < height; y += 1) {\n const row = r.map(x => {\n return {\n x,\n y,\n top: closed || y > 0,\n left: closed || x > 0,\n bottom: closed || y < (height - 1),\n right: closed || x < (width - 1)\n };\n });\n maze.push(row);\n }\n\n // All rows except last:\n initial(maze).forEach((row, y) => { // TODO initial temp?\n populateMissingSets(row, random);\n mergeRandomSetsIn(row, random);\n addSetExits(row, maze[y + 1], random);\n });\n\n const lastRow = last(maze);\n populateMissingSets(lastRow, random);\n mergeRandomSetsIn(lastRow, random, 1);\n\n return maze;\n}\n\nexport default generate;\n"],"names":["initial","array","slice","range","n","end","Array","from","keys","map","k","uniq","Set","populateMissingSets","row","random","setsInUse","set","filter","Boolean","availableSets","c","length","d","reduce","a","b","includes","sort","box","forEach","i","mergeRandomSetsIn","probability","current","x","next","differentSets","shouldMerge","oldSet","newSet","mergeSetWith","right","left","width","height","closed","seed","t","Math","imul","mulberry32","maze","r","y","top","bottom","push","nextRow","setsInRow","Object","values","list","key","dict","item","prev","groupBy","ceil","index","lastIndex","result","rand","floor","value","sampleSize","exit","below","addSetExits","lastRow"],"mappings":"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"}