Skip to content

Instantly share code, notes, and snippets.

@gdm85
Forked from crates/jsbin.banekiq.js
Created August 17, 2020 11:26
Show Gist options
  • Save gdm85/8dbb792011e22cf195db8047eb0d1ae7 to your computer and use it in GitHub Desktop.
Save gdm85/8dbb792011e22cf195db8047eb0d1ae7 to your computer and use it in GitHub Desktop.
Entombed maze generator // source: https://jsbin.com/banekiq
// Entombed maze generator
// More info at https://www.semanticscholar.org/paper/Entombed%3A-An-archaeological-examination-of-an-Atari-Aycock-Copplestone/fc18c3f88be41e4102654c1d883b907d7bfae6d2
// Written by reddit.com/user/JaggedMetalOs
// Here's what I'd like to see added: (Crates)
// * There must be at least one valid path from start to exit
// * Areas that are completely enclosed should have no openings inside
// * Avoid shorter paths that go less far, in favor of longer, meandering ones
// * It would be cool to see an AI that can generate complex mazes!
// Maze generation rules lookup table.
// Presented vertically for easy copy&paste of rules
// Entombed's own rule is "iiiroorriiiiroooiiirooooroirrooo"
// Rule "iooioooiiooioooiiooioooiiooioooi" is identical to rule 110 and so is turing complete
//
// Key - i = filled, o = empty, r = random
//
// a = ooooooooooooooooiiiiiiiiiiiiiiii
// b = ooooooooiiiiiiiiooooooooiiiiiiii
// c = ooooiiiiooooiiiiooooiiiiooooiiii
// d = ooiiooiiooiiooiiooiiooiiooiiooii
// e = oioioioioioioioioioioioioioioioi
// --------------------------------
var rule = "iiiroorriiiiroooiiirooooroirrooo"
// Starting row
// In the game this is "oooooooo"
// but can be made any width and any initial pattern
var defaultRow = "oiooiooo"
// Begin generation code here ---------
generate();
function generate(){
var currentRow = defaultRow;
var columns = defaultRow.length;
var lastColumn = columns - 1;
var html = [];
html.push("<pre>Entombed maze generator\nRule="+rule+"\r<a href='javascript:generate()'>New maze</a></pre>");
html.push("<div class=c>");
drawRow(html, currentRow);
for (var line=0; line<256; line++) {
// Main generation loop here
var prevRow = currentRow;
currentRow = "";
// Generate row by parsing previous and current row data.
// Similar to elementary cellular automaton
for (var column = 0; column < columns; column++){
// Read existing walls in the following pattern:
// | cde|
// |ab# |
var a = currentRow[column-2];
var b = currentRow[column-1];
var c = prevRow[column-1];
var d = prevRow[column];
var e = prevRow[column+1];
// Left/right edge cases, JS ignores out of bounds access
if(column == 0){
a = "i";
b = "o";
c = randomWall();
}
else if(column == 1){
a = "o";
}
else if(column == lastColumn){
e = randomWall();
}
currentRow += nextWall(a,b,c,d,e);
}
drawRow(html, currentRow);
}
html.push("</div>");
document.body.innerHTML = html.join("");
}
// End generation code here ---------
function nextWall(a,b,c,d,e){
// Convert abcde into binary offset in lookup table
var offset = (a=="i"?16:0)
+ (b=="i"?8:0)
+ (c=="i"?4:0)
+ (d=="i"?2:0)
+ (e=="i"?1:0);
var lookup = rule[offset];
if(lookup == "o") return "o";
if(lookup == "i") return "i";
// All other cases assume random
return randomWall();
}
function randomWall(){
return Math.random() > 0.5?"i" : "o";
}
function drawRow(html, rowData){
// Always start with 2 walls
rowData = "ii" + rowData;
var i;
for(i=0; i<rowData.length; i++){
html.push("<div class="+rowData[i]+">");
}
for(i=0; i<rowData.length; i++){
html.push("</div>");
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Entombed maze generator</title>
<style>
body{color:white; background-color:black;}
a{color:white;}
.c{float:left;}
.i,.o{height:10px; padding:0 10px; font-size:0;}
.i{background-color:white;}
.o{background-color:black;}
</style>
</head>
<body>
<script id="jsbin-javascript">
// Entombed maze generator
// More info at https://www.semanticscholar.org/paper/Entombed%3A-An-archaeological-examination-of-an-Atari-Aycock-Copplestone/fc18c3f88be41e4102654c1d883b907d7bfae6d2
// Written by reddit.com/user/JaggedMetalOs
// Maze generation rules lookup table.
// Presented vertically for easy copy&paste of rules
// Entombed's own rule is "iiiroorriiiiroooiiirooooroirrooo"
// Rule "iooioooiiooioooiiooioooiiooioooi" is identical to rule 110 and so is turing complete
//
// Key - i = filled, o = empty, r = random
//
// a = ooooooooooooooooiiiiiiiiiiiiiiii
// b = ooooooooiiiiiiiiooooooooiiiiiiii
// c = ooooiiiiooooiiiiooooiiiiooooiiii
// d = ooiiooiiooiiooiiooiiooiiooiiooii
// e = oioioioioioioioioioioioioioioioi
// --------------------------------
var rule = "iiiroorriiiiroooiiirooooroirrooo"
// Starting row
// In the game this is "oooooooo"
// but can be made any width and any initial pattern
var defaultRow = "oiooiooo"
// Begin generation code here ---------
generate();
function generate(){
var currentRow = defaultRow;
var columns = defaultRow.length;
var lastColumn = columns - 1;
var html = [];
html.push("<pre>Entombed maze generator\nRule="+rule+"\r<a href='javascript:generate()'>New maze</a></pre>");
html.push("<div class=c>");
drawRow(html, currentRow);
for (var line=0; line<256; line++) {
// Main generation loop here
var prevRow = currentRow;
currentRow = "";
// Generate row by parsing previous and current row data.
// Similar to elementary cellular automaton
for (var column = 0; column < columns; column++){
// Read existing walls in the following pattern:
// | cde|
// |ab# |
var a = currentRow[column-2];
var b = currentRow[column-1];
var c = prevRow[column-1];
var d = prevRow[column];
var e = prevRow[column+1];
// Left/right edge cases, JS ignores out of bounds access
if(column == 0){
a = "i";
b = "o";
c = randomWall();
}
else if(column == 1){
a = "o";
}
else if(column == lastColumn){
e = randomWall();
}
currentRow += nextWall(a,b,c,d,e);
}
drawRow(html, currentRow);
}
html.push("</div>");
document.body.innerHTML = html.join("");
}
// End generation code here ---------
function nextWall(a,b,c,d,e){
// Convert abcde into binary offset in lookup table
var offset = (a=="i"?16:0)
+ (b=="i"?8:0)
+ (c=="i"?4:0)
+ (d=="i"?2:0)
+ (e=="i"?1:0);
var lookup = rule[offset];
if(lookup == "o") return "o";
if(lookup == "i") return "i";
// All other cases assume random
return randomWall();
}
function randomWall(){
return Math.random() > 0.5?"i" : "o";
}
function drawRow(html, rowData){
// Always start with 2 walls
rowData = "ii" + rowData;
var i;
for(i=0; i<rowData.length; i++){
html.push("<div class="+rowData[i]+">");
}
for(i=0; i<rowData.length; i++){
html.push("</div>");
}
}
</script>
<script id="jsbin-source-javascript" type="text/javascript">// Entombed maze generator
// More info at https://www.semanticscholar.org/paper/Entombed%3A-An-archaeological-examination-of-an-Atari-Aycock-Copplestone/fc18c3f88be41e4102654c1d883b907d7bfae6d2
// Written by reddit.com/user/JaggedMetalOs
// Maze generation rules lookup table.
// Presented vertically for easy copy&paste of rules
// Entombed's own rule is "iiiroorriiiiroooiiirooooroirrooo"
// Rule "iooioooiiooioooiiooioooiiooioooi" is identical to rule 110 and so is turing complete
//
// Key - i = filled, o = empty, r = random
//
// a = ooooooooooooooooiiiiiiiiiiiiiiii
// b = ooooooooiiiiiiiiooooooooiiiiiiii
// c = ooooiiiiooooiiiiooooiiiiooooiiii
// d = ooiiooiiooiiooiiooiiooiiooiiooii
// e = oioioioioioioioioioioioioioioioi
// --------------------------------
var rule = "iiiroorriiiiroooiiirooooroirrooo"
// Starting row
// In the game this is "oooooooo"
// but can be made any width and any initial pattern
var defaultRow = "oiooiooo"
// Begin generation code here ---------
generate();
function generate(){
var currentRow = defaultRow;
var columns = defaultRow.length;
var lastColumn = columns - 1;
var html = [];
html.push("<pre>Entombed maze generator\nRule="+rule+"\r<a href='javascript:generate()'>New maze</a></pre>");
html.push("<div class=c>");
drawRow(html, currentRow);
for (var line=0; line<256; line++) {
// Main generation loop here
var prevRow = currentRow;
currentRow = "";
// Generate row by parsing previous and current row data.
// Similar to elementary cellular automaton
for (var column = 0; column < columns; column++){
// Read existing walls in the following pattern:
// | cde|
// |ab# |
var a = currentRow[column-2];
var b = currentRow[column-1];
var c = prevRow[column-1];
var d = prevRow[column];
var e = prevRow[column+1];
// Left/right edge cases, JS ignores out of bounds access
if(column == 0){
a = "i";
b = "o";
c = randomWall();
}
else if(column == 1){
a = "o";
}
else if(column == lastColumn){
e = randomWall();
}
currentRow += nextWall(a,b,c,d,e);
}
drawRow(html, currentRow);
}
html.push("</div>");
document.body.innerHTML = html.join("");
}
// End generation code here ---------
function nextWall(a,b,c,d,e){
// Convert abcde into binary offset in lookup table
var offset = (a=="i"?16:0)
+ (b=="i"?8:0)
+ (c=="i"?4:0)
+ (d=="i"?2:0)
+ (e=="i"?1:0);
var lookup = rule[offset];
if(lookup == "o") return "o";
if(lookup == "i") return "i";
// All other cases assume random
return randomWall();
}
function randomWall(){
return Math.random() > 0.5?"i" : "o";
}
function drawRow(html, rowData){
// Always start with 2 walls
rowData = "ii" + rowData;
var i;
for(i=0; i<rowData.length; i++){
html.push("<div class="+rowData[i]+">");
}
for(i=0; i<rowData.length; i++){
html.push("</div>");
}
}
</script></body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment