Skip to content

Instantly share code, notes, and snippets.

@tswaters
Last active September 22, 2018 20:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tswaters/2738a4e6f43abeaf12f8520e0e1c8f62 to your computer and use it in GitHub Desktop.
Save tswaters/2738a4e6f43abeaf12f8520e0e1c8f62 to your computer and use it in GitHub Desktop.
maze generation in terminal
'use strict'
const readline = require('readline')
const NORTH = 0b1000
const SOUTH = 0b0100
const EAST = 0b0010
const WEST = 0b0001
const ALL = 0b1111
const flip = dir =>
[NORTH + SOUTH, EAST + WEST].reduce((memo, mask) =>
memo || mask & dir && ~(mask & dir) & ALL & mask
, null)
// javascript: y u no have match expression?!
const glyph = value => {
switch (value) {
case NORTH + SOUTH + EAST + WEST: return '\u254B'
case NORTH + SOUTH + EAST: return '\u2523'
case NORTH + SOUTH + WEST: return '\u252B'
case NORTH + SOUTH: return '\u2503'
case NORTH + EAST + WEST: return '\u253B'
case NORTH + EAST: return '\u2517'
case NORTH + WEST: return '\u251B'
case NORTH: return '\u2579'
case SOUTH + EAST + WEST: return '\u2533'
case SOUTH + EAST: return '\u250F'
case SOUTH + WEST: return '\u2513'
case SOUTH: return '\u257B'
case EAST + WEST: return '\u2501'
case EAST: return '\u257A'
case WEST: return '\u2578'
}
}
const nodes = generate(30, 50)
print(30, 50)
function generate (rows, cols) {
const nodes = {}
const startX = parseInt(Math.random() * cols)
const startY = parseInt(Math.random() * rows)
for (let x = 0; x < cols; x++ ) {
for (let y = 0; y < rows; y++) {
nodes[`${x},${y}`] = {x, y, parent: null, dirs: ALL, walls: ALL}
}
}
const start = nodes[`${startX},${startY}`]
start.parent = start
let last = null
while (last != start) {
last = link(last || start, rows, cols)
}
return nodes
function link (node, rows, cols) {
// While there are directions still unexplored
while (node.dirs) {
let x = node.x
let y = node.y
// Randomly pick one direction
const dir = 1 << Math.random() * 4
// If it has already been explored - try again
if (~node.dirs & dir) { continue }
// Mark direction as explored
node.dirs &= ~dir
// If it's not possible to go that direction - try again
if (dir === NORTH && node.y === 0) { continue }
if (dir === SOUTH && node.y + 1 >= rows) { continue }
if (dir === EAST && node.x + 1 >= cols) { continue }
if (dir === WEST && node.x === 0) { continue }
// Increment for the given direction
switch (dir) {
case EAST: x = node.x + 1; break
case SOUTH: y = node.y + 1; break
case WEST: x = node.x - 1; break
case NORTH: y = node.y - 1; break
}
// Get destination node
const flipped = flip(dir)
const dest = nodes[`${x},${y}`]
// Make sure that destination node is not a wall
// If destination is a linked node already - abort
// otherwise adopt nodes & tear down those walls.
if (
node.walls & dir &&
dest.walls & flipped &&
dest.parent === null
) {
dest.parent = node
node.walls &= ~dir
dest.walls &= ~flipped
return dest
}
}
return node.parent
}
}
function print (rows, cols) {
process.stderr.write('\x1B[2J')
for (let x = 0; x <= cols; x += 1 ) {
for (let y = 0; y <= rows; y += 1) {
const top_left = nodes[`${x - 1},${y - 1}`]
const top_right = nodes[`${x},${y - 1}`]
const bottom_left = nodes[`${x - 1},${y}`]
const bottom_right = nodes[`${x},${y}`]
let glyph1 = 0
if (top_left && top_left.walls & EAST && (top_right && top_right.walls & WEST)) { glyph1 |= NORTH }
if (bottom_left && bottom_left.walls & EAST && (bottom_right && bottom_right.walls & WEST)) { glyph1 |= SOUTH }
if (top_right && top_right.walls & SOUTH && (bottom_right && bottom_right.walls & NORTH)) { glyph1 |= EAST }
if (top_left && top_left.walls & SOUTH && (bottom_left && bottom_left.walls & NORTH)) { glyph1 |= WEST }
// if corners or edges, show a wall
if (!top_left && !bottom_left && !bottom_right) { glyph1 |= NORTH + EAST }
else if (!top_left && !top_right && !bottom_left) { glyph1 |= SOUTH + EAST }
else if (!top_left && !top_right && !bottom_right) { glyph1 |= SOUTH + WEST }
else if (!top_right && !bottom_left && !bottom_left) { glyph1 |= NORTH + WEST }
else if (!top_right && !top_left || !bottom_left && !bottom_right) { glyph1 |= EAST + WEST }
else if (!top_left && !bottom_left || !top_right && !bottom_right) { glyph1 |= NORTH + SOUTH }
readline.cursorTo(process.stderr, x, y)
process.stderr.write(glyph(glyph1))
}
}
readline.cursorTo(process.stderr, cols, rows + 1)
process.stderr.write('')
}
$ node maze.js
┏━┳━┳━┳━┳━━┳━━━┳━━┳━━┳━━┳━━━━━┳━┳━━━━━━━┳━━━━┳━━┳━┓
┃╺┛╻┃╻┃╻┃╻╻┃╺━┓┃╺━┫╺┓┣╸╻┗━━┳╸╻┃╻┗┳━━━━━┓┃╻┏┳╸┃╺┓╹╻┃
┃╺━┫┃┃╹┃╹┃┃┗┳╸┃┣━┓┣╸┃┃┏┻━┳╸┃╺┫┃┣┓┃╺┳━━╸┃╹┃┃╹┏┻┓┣━┛┃
┣╸┏┛┃┣┳┻━┫┣┓┃┏┫╹╻╹┃┏┫┃┃┏╸┃┏┻╸┃╹┃┃┗┓┗━━┓┗━┛┃╺┛╻┗┛┏╸┃
┃┏┫╻┃┃┃╺┓╹┃┃╹┃┃┏┻━┛┃┃╹┃┃╺┛┃┏━┻━┫┗┓┃╺━┓┣━━━┻━┳┻┳━┛┏┫
┃┃┃┗┛┃┗┓┣┳┛┗━┛╹┃┏━━┛┗━┫┗┳━┛┃╺━━┫╻╹┃┏━┛┃╺━━━━┛╻╹┏━┛┃
┃┃┗━━┛╻┃┃╹╺┳━━━┫┃┏━━┓╺┻╸┣━╸┃┏━┓╹┣━┻┛┏━┛┏━━━┳━╋━┛╺┓┃
┃┃╺┓╺━┻┫┗━┓┗┳━╸┃┗┛┏┓┣━━┓╹┏━┫┣╸┗━┫╺┳━┫┏━┛┏╸┏┛╻╹┏━┓┗┫
┃┃┏┻━┓╻┗━┓┗┓╹╻┏┻━━┛┃┃┏╸┣━┛╻┃╹┏━┓┗┓┃╻┃┃╺━┫╺┫╺┻┳┛╻┣╸┃
┃┗┛┏┓┣┻┓╺┻┓┗┳┻┫╺┳╸╻┃┃┃╺┛┏━┫┗━┛╻┗┓╹┃┃┃┗┳┓┗┓┗━┓┃┏┛┃╺┫
┣━┳┛╹┃╻┣━┓┗┓╹╻╹┏┛┏┻┛┃┣━━┛╻┗━┳━┻┓┣━┛┗┻┓┃┗╸┗┳╸┃┃┃┏┻╸┃
┃┏┛┏━┫┃╹╻┗╸┗━╋━┛╻┃╺┓┃┗━╸┏┻╸┏┛┏╸╹┣━━┓╺┫┣━┳╸┃╺┫┗┛┃┏╸┃
┃┃┏┛╻┃┣━┛┏━┓┏┛┏━┛┣┓┗┻╸┏━┻┓┏┫╺┻┳━┫┏╸┃╻┃╹╻┗┳┻┓┣━╸┃┗┓┃
┃╹┃╺┫╹┣━┓┃╻┗┛┏┫┏━┛┗━┳━┛┏╸┃╹┣━┓┗┓╹┃╺┫┃┗━╋╸┃╻╹┃╺━┻┓┃┃
┃╺┻┓┃┏┛╻┗┛┣━━┛╹┗┓╻┏╸┃┏━┛╺┻━┛╻╹┏┻━┻┓┣┻╸┏┛┏┛┃┏┻━━╸┃┗┫
┣┳╸┃┣┛┏┻┓┏┻┳━━━┓┗┫┣━┛┣━┓┏━┓┏┻━┛╻╺━┛┃┏━┫┏┫╻┃┃╺┳━━┻╸┃
┃┃┏┛┃┏┫╻╹┃╻╹┏━┓┣┓╹┃┏━┫╻┗┫╻┗┫┏━━╋━━━┫╹╻┃┃╹┃┗┻┓┃┏━┳╸┃
┃┃╹╻┃┃╹┗┳┛┣━┛┏┛┃┗╸┃╹╻┃┣┓╹┣╸┃┃╺━┫┏╸┏┛╺┫┃┗━┻┓╺┛┃┃╺┛┏┫
┃┗━┫┃┗━━┫╺┻━╸┃┏┛╺━╋━┫┃╹┣━┛┏┛┣━╸┃┃╺┛╺┳┛┗┳━╸┣━━┫┃╺━┛┃
┃╻┏┛┣━━╸┣━━┳┓┃┃┏━┓╹╻┃┗┓┃╻┏┛┏┫╺━┛┣━┳━┛┏━┫╺━┫┏╸╹┣━┳╸┃
┃┃┃┏┛┏┳╸┃╻╻╹┃┃┗┫╻┗━┫┃╺┫┃┗┛┏┛┃╺┳┳┻╸┃╺━┛╻┗┳╸┃┗┳━┛╺┫╺┫
┃┃┃┃╺┫┃┏┛┃┃┏┛┣╸┃┗┳┓┣┻┓╹┣━━┻╸┣╸┃╹╻┏┻━━┳┻┓┃╺┫╻┃┏━┓┣╸┃
┃┃┃┣╸┃╹┃╺┫┃┃╺┫╺╋╸┃┃╹╻┗━┻╸╻┏━┫┏┛┏┛┃╺┓╺┫╻┃┗╸┣┛┣┛╻┃┃╺┫
┃┃┃┃╺╋━╋╸┃┃┗┓┗┓╹┏┛┗━┻━┳╸╻┣┛╻┃┗┓┃╺┻╸┣┓╹┃┣━━┛╻┃┏┛┃┗╸┃
┃┗┛┣┓╹╻╹┏┛┃┏┻╸┣━┻┓╻╺━┓┃╺╋┛┏┫┗╸┃┣━━━┛┗━┫╹┏┓╻┣┛┃╺╋━━┫
┃╺┳┛┣┳┻━┫╺╋┛┏━┛╻╻┗┻━┓┣┻┓┃╺┫┗┳━┫┣╸┏━┳━╸┗━┛┃┗┛┏┻┓┃╺┓┃
┣╸┃╻┃╹┏╸┣┓┃╺┻━━┫┣┳━┓┃╹╻┃┗┓┃╻╹╻╹╹╻┃╻┗┳━┳━┓┗━┳┛╻┃┃┏┛┃
┃╺┛┃┗━┛╻┃┃┗┳━━┓╹┃┃╻╹┣━┛┃╻┃┣┻━┻━┳┻┛┣┓╹╻╹╻┗┳━┫┏┛┃╹┃╻┃
┣━┳┻━━━┫┃┗┓┃┏╸┣━┛┃┗┳┛┏╸┃┃┃╹┏┳━┓╹┏━┛┗┳┻━┻┓╹╻┃┗┓┃╺┫┃┃
┃╻╹╻╺━━┛┗╸┃╹┃╺┛╻╺┻╸┗╸┃╺┫┗┻━┛╹╻┗━┛╺┓╺┛╺┓╺┻━┛┗╸┃┗━┛┃┃
┗┻━┻━━━━━━┻━┻━━┻━━━━━┻━┻━━━━━┻━━━━┻━━━┻━━━━━━┻━━━┻┛
$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment