|
'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('') |
|
|
|
} |