#!/usr/bin/python3 "Generate mazes." import random import sys # Using the heavy box-drawing characters from Unicode, stored in # parallel arrays. chars = '━┃┏┓┗┛┣┫┳┻╋╸╺╹╻ ' left = '1001010111110000' # 1 if line touches left, 0 otherwise right = '1010101011101000' # mutatis mutandis top = '0100111101100100' bottom = '0111001110100010' def render(h, v): for hline, upline, downline in zip(h, v[:-1], v[1:]): row = [] for r, l, u, d in zip(hline[1:], hline[:-1], upline, downline): row.append(random.choice([c for i, c in enumerate(chars) if l == left[i] and r == right[i] and u == top[i] and d == bottom[i]])) yield ''.join(row) class UnionFind: def __init__(self): self.parent = {} def root(self, cell): descendants = [] while self.parent.get(cell, cell) != cell: descendants.append(cell) cell = self.parent[cell] # We have reached the end of the chain; now snap all the # pointers to it. for descendant in descendants: self.parent[descendant] = cell return cell def connect(self, start, end): start = self.root(start) end = self.root(end) self.parent[start] = end def connected(self, a, b): return self.root(a) == self.root(b) def genmaze(w, h): h, v = ([['0'] + ['1'] * w + ['0'] for i in range(h+1)], [['0'] * (w+1)] + [['1'] * (w+1) for i in range(h)] + [['0'] * (w+1)]) h[0][1] = '0' # entry h[-1][-2] = '0' # exit walls = ([('h', r, c) for r in range(1, len(h)-1) for c in range(len(h[0]))] + [('v', r, c) for r in range(len(v)) for c in range(1, len(v[0])-1)]) random.shuffle(walls) state = UnionFind() for wall in walls: t, r, c = wall cell_b = (r+1, c) if t == 'h' else (r, c+1) if not state.connected((r, c), cell_b): state.connect((r, c), cell_b) (h if t == 'h' else v)[r][c] = '0' return h, v if __name__ == '__main__': h, v = genmaze(64, 16) if len(sys.argv) == 1 else genmaze(int(sys.argv[1]), int(sys.argv[2])) for line in render(h, v): print(line)