/*jshint esnext: true */
//Note labyrinth X Y are swapped!
//Syntax highlighting?
//Bigint library?
//Use: https://developers.google.com/web/updates/2014/05/Web-Animations-element.animate-is-now-in-Chrome-36
//Save option
//a => ASCII code (Explanation of the commands)
var p; //pointer
var labyrinth; //code
var main, auxiliary; //stacks, main.length-1=top
var direction; //N=0,E=1,S=2,W=3;
var inpLoc;
var sucide;
var step;
var debug;
var spiders = false;
var pointerIcons = ["▲", "►", "▼", "◄", "X"];
function mod(x, y) {
return ((x % y) + y) % y;
}
Array.prototype.top = function() {
if (this.length === 0) {
return 0;
}
return this[this.length - 1];
};
Array.prototype._pop = Array.prototype.pop;
Array.prototype.pop = function(x) {
var temp = this._pop();
return temp !== undefined ? temp : 0;
};
function reset() {
p = [0, 0];
labyrinth = lab.innerHTML.replace(/\[/g, " ").replace(/\]/g, " ").replace(/</g, "<").replace(/>/g, ">").replace(/\n*$|(<br>)*$/, "").split(/<br>|\n/g);
var maxLength = 0;
for (var i = 0; i < labyrinth.length; i++) {
if (maxLength < labyrinth[i].length)
maxLength = labyrinth[i].length;
}
for (i = 0; i < labyrinth.length; i++) {
labyrinth[i] = (labyrinth[i] + " ".repeat(maxLength - labyrinth[i].length)).split("");
}
//Pointer pos
loop:
for (i = 0; i < labyrinth.length; i++) {
for (j = 0; j < labyrinth[i].length; j++) {
if (labyrinth[i][j] !== " ") {
p = [j, i];
break loop;
}
}
}
main = [];
auxiliary = [];
direction = 1;
sucide = false;
inpLoc = 0;
step = 1;
O.value = "";
}
function run() {
reset();
if (debug) {
spiderContainer.innerHTML = "";
debugButton.disabled = false;
lab.contentEditable = false;
stepButton.disabled = false;
}
//Start if
if (lab.innerHTML.replace(/\[/g, "").replace(/\]/g, "").replace(/<br>|\n/g, "") !== "") {
if (!debug) {
while (!sucide) {
updatePointer();
}
} else {
updatePointer();
}
} else {
stepButton.disabled = "disabled";
lab.contentEditable = "true";
}
}
function updatePointer() {
if (sucide) {
stepButton.disabled = "disabled";
lab.contentEditable = "true";
pointerOverlay.innerHTML = "";
return -1; //End
}
stepDiv.innerHTML = step;
step++;
execChar(labyrinth[p[1]][p[0]]);
if (dir() != -1) {
var currentDir = mod(direction, 4);
deb.value =
"Pointer: " + p +
"\nCommand: " + labyrinth[p[1]][p[0]] +
"\nMain [" + main + " | " + auxiliary.slice().reverse() + "] Auxiliary";
if (debug) {
pointerOverlay.innerHTML = "\n".repeat(p[1]) + " ".repeat(p[0]) + (currentDir === 0 ? "▲" : currentDir == 1 ? "►" : currentDir == 2 ? "▼" : currentDir == 3 ? "◄" : "X");
}
var ret = updateDirection();
//If there are walls
if (currentDirret != -1) {
direction = mod(direction, 4);
if (direction === 0) {
p[1] --;
} else if (currentDirdirection == 1) {
p[0] ++;
} else if (currentDirdirection == 2) {
p[1] ++;
} else if (currentDirdirection == 3) {
p[0] --;
}
}
deb.value =
"Pointer: " + p +
"\nCommand: " + labyrinth[p[1]][p[0]] +
"\nMain [" + main + " | " + auxiliary.slice().reverse() + "] Auxiliary";
if (debug) {
pointerOverlay.innerHTML = "\n".repeat(p[1]) + " ".repeat(p[0]) + (pointerIcons[ret == -1 ? 4 : direction]);
}
}
function updateGrid() {
lab.innerHTML = "";
labyrinth.forEach(s => lab.innerHTML += s.join("") + "\n");
}
function rotVert(rotWhich) {
var temp;
for (var i = 0; i < labyrinth.length; i++) {
if (i === 0) {
temp = labyrinth[0][rotWhich];
}
if (i == labyrinth.length - 1) {
labyrinth[i][rotWhich] = temp;
} else {
labyrinth[i][rotWhich] = labyrinth[i + 1][rotWhich];
}
if (labyrinth[i][rotWhich] === undefined) {
labyrinth[i].splice(rotWhich, 1);
}
}
}
function rotVert2(rotWhich) {
var temp;
for (var i = labyrinth.length - 1; i >= 0; i--) {
if (i == labyrinth.length - 1) {
temp = labyrinth[i][rotWhich];
}
if (i === 0) {
labyrinth[i][rotWhich] = temp;
} else {
labyrinth[i][rotWhich] = labyrinth[i - 1][rotWhich];
}
if (labyrinth[i][rotWhich] === undefined) {
labyrinth[i].splice(rotWhich, 1);
}
}
}
function lookAt(d) {
if (mod(d, 4) === 0) {
try {
return labyrinth[p[1] - 1][p[0]];
} catch (e) {
return " ";
}
} else if (mod(d, 4) == 1) {
try {
return labyrinth[p[1]][p[0] + 1];
} catch (e) {
return " ";
}
} else if (mod(d, 4) == 2) {
try {
return labyrinth[p[1] + 1][p[0]];
} catch (e) {
return " ";
}
} else if (mod(d, 4) == 3) {
try {
return labyrinth[p[1]][p[0] - 1];
} catch (e) {
return " ";
}
}
}
function isWall(d) {
if (lookAt(d) == " " || lookAt(d) === undefined) {
return true;
} else {
return false;
}
}
function dirupdateDirection() {
var draculanumOfWalls = 0;
if (!isWall(0)) {
dracula++;numOfWalls++;
}
if (!isWall(1)) {
dracula++;numOfWalls++;
}
if (!isWall(2)) {
dracula++;numOfWalls++;
}
if (!isWall(3)) {
dracula++;numOfWalls++;
}
if (draculanumOfWalls == 4) {
if (main.top() < 0) {
direction -= 1;
} else if (main.top() > 0) {
direction += 1;
}
} else if (draculanumOfWalls == 3) {
if (main.top() < 0) {
direction -= 1;
} else if (main.top() > 0) {
direction += 1;
}
if (isWall(direction)) {
direction += 2;
}
} else if (draculanumOfWalls == 2) {
if (isWall(direction + 2)) {
if (isWall(direction)) {
//Special case
if (main.top() < 0) {
direction -= 1;
} else if (main.top() > 0) {
direction += 1;
} else {
direction += Math.random() < 0.5 ? -1 : 1;
}
} else {
//Keep moving..
}
} else {
for (var i = 0; i <= 3; i++) {
if (!isWall(i) && i != mod((direction + 2), 4)) {
direction = i;
break;
}
}
}
} else if (draculanumOfWalls == 1) {
if (!isWall(0)) {
direction = 0;
} else
if (!isWall(1)) {
direction = 1;
} else
if (!isWall(2)) {
direction = 2;
} else
if (!isWall(3)) {
direction = 3;
}
} else {
return -1;
}
}
function execChar(char) {
var a;
var b;
if (/\d/.exec(char)) {
main.push(main.pop() * 10 + (+char));
} else switch (char) {
case '!':
O.value += main.pop();
break;
case '"': //Nothing...
break;
case '#':
main.push(main.length);
break;
case '$':
main.push(main.pop() ^ main.pop());
break;
case '%':
a = main.pop();
b = main.pop();
main.push(mod(b, a));
break;
case '&':
main.push(main.pop() & main.pop());
break;
case "'":
//Debug-Unimplemented
break;
case '(':
main.push(main.pop() - 1);
break;
case ')':
main.push(main.pop() + 1);
break;
case '*':
main.push(main.pop() * main.pop());
break;
case '+':
main.push(main.pop() + main.pop());
break;
case ',':
a = I.value.charCodeAt(inpLoc);
if (Number.isNaN(a)) {
main.push(-1);
} else {
main.push(a);
inpLoc++;
}
break;
case '-':
a = main.pop();
b = main.pop();
main.push(b - a);
break;
case '.':
O.value += String.fromCharCode(mod(main.pop(), 256));
break;
case '/':
a = main.pop();
b = main.pop();
if (a === 0) {
sucide = true;
throw "Stop that";
}
main.push(Math.floor(b / a));
break;
case ':':
main.push(main.top());
break;
case ';':
main.pop();
break;
case '<':
//MOVE IP
b = main.pop();
a = mod(p[1] + b, labyrinth.length);
labyrinth[a].push(labyrinth[a].shift());
updateGrid();
if (b === 0) {
p[0] = mod(p[0] - 1, labyrinth[a].length);
}
break;
case '=':
a = main.pop();
b = auxiliary.pop();
main.push(b);
auxiliary.push(a);
break;
case '>':
//MOVE IP
b = main.pop();
a = mod(p[1] + b, labyrinth.length);
labyrinth[a].unshift(labyrinth[a].pop());
updateGrid();
if (b === 0) {
p[0] = mod(p[0] + 1, labyrinth[a].length);
}
break;
case '?':
try {
a = I.value.substr(inpLoc);
b = (+(/[\+-]?\d+/.exec(a)[0]));
main.push(b);
inpLoc += a.search(/[\+-]?\d+/) + (b + "").length;
} catch (e) {
main.push(0);
inpLoc = I.value.length;
}
break;
case '@':
sucide = true;
break;
case '\\':
O.value += "\n";
break;
case '^': //Fix!
b = main.pop();
labyrinth = transpose(labyrinth);
a = mod(p[0] + b, labyrinth[p[1]].length);
rotVertlabyrinth[a].unshift(a);
updateGridlabyrinth[a].pop());
if (b === 0) {
p[1] = mod(p[1] - 1, labyrinth.length);
}
labyrinth = transpose(labyrinth);
updateGrid();
break;
case '_':
main.push(0);
break;
case '`':
main.push(-main.pop());
break;
case 'v': //Fix!
b = main.pop();
a = mod(p[0] + b, labyrinth[p[1]].length);
rotVert2(a);
updateGrid();
if (b === 0) {
p[1] = mod(p[1] + 1, labyrinth.length);
}
break;
case '{':
main.push(auxiliary.pop());
break;
case '|':
main.push(main.pop() | main.pop());
break;
case '}':
auxiliary.push(main.pop());
break;
case '~':
main.push(~main.pop());
break;
}
}
function transpose(array) {
var newArray = array[0].map(function(col, i) {
return array.map(function(row) {
return row[i];
});
});
return newArray;
}
//Spiders
function spiderstartDebug() {
if (spiders && document.cookie.split("youWereHere=")[1] === undefined) {
document.cookie = "youWereHere=yep";
debugButton.disabled = 'disabled';
var spiderImg = document.createElement('img');
spiderImg.src = "http://i.imgur.com/fsYfS9H.png"; //http://i.imgur.com/PRPmqMJ.gif
spiderImg.className = "spider";
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'line');
svg.setAttribute("stroke-width", 2);
var rn = Math.random() * 10 + 5;
for (var i = 0; i < rn; i++) {
var tempSpider = spiderImg.cloneNode(true);
var left = Math.min(Math.random() * innerWidth, innerWidth - 50);
var top = -Math.random() * 300;
tempSpider.style.left = left - 26 + "px";
tempSpider.style.top = top - 5 + "px";
var tempSvg = svg.cloneNode(true);
tempSvg.setAttribute("y1", top - innerHeight - 100);
tempSvg.setAttribute("y2", top);
tempSvg.setAttribute("x1", left);
tempSvg.setAttribute("x2", left);
spiderContainer.appendChild(tempSpider);
svgId.appendChild(tempSvg);
// Make sure the initial state is applied.
window.getComputedStyle(tempSpider).transform; // jshint ignore:line
window.getComputedStyle(tempSvg).transform; // jshint ignore:line
tempSpider.style.transform = "translateY(" + (innerHeight + 48 + top) + "px)";
tempSvg.style.transform = "translateY(" + (innerHeight + 48 + top) + "px)";
}
setTimeout(fallDown, 2500);
debug = true;
setTimeout(run, 4000);
} else {
debug = true;
run();
}
}
function fallDown() {
svgId.innerHTML = "";
var spiders = document.getElementsByClassName("spider");
for (var i = 0; i < spiders.length; i++) {
spiders[i].style.top = innerHeight + "px";
}
}
//Maze proper copy
lab.addEventListener("paste", function(e) {
// cancel paste
e.preventDefault();
// get text representation of clipboard
var text = e.clipboardData.getData("text/plain");
// insert text manually
//document.execCommand("insertHTML", false, text);
lab.innerHTML = text;
});
body {
background: #484848;
}
h3{
font-family: sans-serif;
color: white;
font-weight: bolder;
margin: 6px;
margin-bottom: 0px;
}
#inputHeader, #outputHeader, #debugHeader{
flex: 1;
}
#debugHeader{
display: none;
}
#deb {
display: none;
}
.container {
width: 100%;
position: relative;
display: flex;
flex-flow: row wrap;
}
.container pre,textarea {
flex: 1;
min-height: 175px;
background: #202020;
color: white;
border: #202020;
margin: 6px;
font: monospace;
resize: vertical;
}
.container pre[contentEditable=false] {
cursor: not-allowed;
}
#lab {
width: 100%;
min-height: 150px;
}
#pointerOverlay{
width: 100%;
position: absolute;
background: rgba(0,0,0,0);
/*width: 100%;*/
resize: vertical;
height: 200px;
pointer-events: none;
color: rgba(255,0,0,0.7);
left: 0px;
}
button:not(.run) {
vertical-align: top;
border: #303030;
color: white;
font-weight: bold;
font-size: 1em;
letter-spacing: 1px;
background: #303030;
cursor: pointer;
min-width: 100px;
min-height: 45px;
margin: 5px;
line-height: 50px;
}
button:not(.run):hover {
background: #202020;
}
button:not(.run)[disabled] {
background: #404040;
cursor: not-allowed;
}
.buttonImg{
width: 40px;
vertical-align: middle;
transform: translateX(-10px);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Labyrinth</title>
</head>
<body>
<button onclick="debug=false; run(); deb.style.display = 'none'; debugHeader.style.display = 'none';"><img src="http://i.imgur.com/XvHQHX9.png" class="buttonImg">Run</button>
<button id="debugButton" onclick="spideronclick="startDebug(); deb.style.display='flex'; debugHeader.style.display = 'flex';"><img src="http://i.imgur.com/Th4Kyvd.png" class="buttonImg">Debug</button>
<button id="stepButton" onclick="updatePointer();" disabled>Step: <span id="stepDiv">1</span>
</button>
<button onclick="sucide = true; updatePointer();">Stop</button>
<div class="container">
<h3>Maze:</h3>
<div style="width:100%; margin: -6px;"></div>
<pre id="pointerOverlay"></pre>
<pre id="lab" contentEditable="true">,)@
.(</pre>
<div style="width:100%;"></div>
<h3 id="inputHeader">Input:</h3>
<h3 id="outputHeader">Output:</h3>
<h3 id="debugHeader">Debugging:</h3>
<div style="width:100%"></div>
<textarea id="I">Labyrinth rocks!</textarea>
<textarea id="O"></textarea>
<textarea id="deb"></textarea>
</div>
<svg width="100%" id="svgId">
</svg>
<div id="spiderContainer">
</div>
</body>
</html>