const BefState = Object.freeze ({ INITIAL: {}, RUNNING: {}, PAUSED: {}, FINISHED: {}, EDIT: {} }); const BefSpeed = Object.freeze ( { SLOW: {val:0,str:'0' }, NORMAL: {val:1,str:'+' }, FAST: {val:2,str:'++'}, SUPERFAST: {val:3,str:'3+'}, MAX: {val:4,str:'4+'}, get: function(i){ for (let x of Object.values(BefSpeed)) if (typeof(x)==='object' && String(x.val) === String(i)) return x; return null; }, max: function( ){let max = 0; for (let x of Object.values(BefSpeed)) if (typeof(x)==='object' ) max = Math.max(x.val); return max; }, }); Array.prototype.peek = function() { return this[this.length - 1]; }; Array.prototype.revjoin = function(sep) { let str=''; for(let i=this.length-1; i >= 0;i--) {if (i t1); break; case '>': this.delta = [+1,0]; break; case '<': this.delta = [-1,0]; break; case '^': this.delta = [0,-1]; break; case 'v': this.delta = [0,+1]; break; case '?': this.delta = [[+1,0],[-1,0],[0,+1],[0,-1]][Math.floor(Math.random()*4)]; break; case '_': this.delta = [[-1,0],[+1,0]][ this.pop_b()?0:1 ]; break; case '|': this.delta = [[0,-1],[0,+1]][ this.pop_b()?0:1 ]; break; case '"': this.strmode = true; break; case ':': this.push_i(this.peek_i()); break; case '\\': t1 = this.pop_i(); t2 = this.pop_i(); this.push_i(t1); this.push_i(t2); break; case '$': this.pop_i(); break; case '.': this.output += this.pop_i() + ' '; break; case ',': this.output += String.fromCharCode(this.pop_i()); break; case '#': this.move(); break; case 'p': t1 = this.pop_i(); t2 = this.pop_i(); t3 = this.pop_i(); this.gridset_i(t2, t1, t3); break; case 'g': t1 = this.pop_i(); t2 = this.pop_i(); this.push_i(this.gridget_i(t2, t1)); break; case '&': t1 = null; while (t1===null||t1===''||isNaN(parseInt(t1[0], 10))){t1=prompt("Input number",null);} this.push_i(parseInt(t1[0], 10)); break; case '~': t1 = null; while (t1===null||t1===''){t1=prompt("Input character",null);} this.push_c(t1[0]); break; case '@': this.delta = [0,0]; break; case '0': this.push_i(0); break; case '1': this.push_i(1); break; case '2': this.push_i(2); break; case '3': this.push_i(3); break; case '4': this.push_i(4); break; case '5': this.push_i(5); break; case '6': this.push_i(6); break; case '7': this.push_i(7); break; case '8': this.push_i(8); break; case '9': this.push_i(9); break; default: window.log('BefRunner: Undefinied command: ' + ichr); } } }; BefObject.prototype.move = function() { this.position[0] += this.delta[0]; this.position[1] += this.delta[1]; if (this.position[0] < 0) this.position[0] += this.width; if (this.position[1] < 0) this.position[1] += this.height; if (this.position[0] >= this.width) this.position[0] -= this.width; if (this.position[1] >= this.height) this.position[1] -= this.height; }; BefObject.prototype.push_i = function(v) { this.stack.push(v); }; BefObject.prototype.pop_i = function() { return this.stack.pop(); }; BefObject.prototype.peek_i = function() { return this.stack.peek(); }; BefObject.prototype.push_b = function(v) { this.stack.push(v?1:0); }; BefObject.prototype.pop_b = function() { return this.stack.pop()!==0; }; BefObject.prototype.push_c = function(v) { this.stack.push(v.charCodeAt(0)); }; BefObject.prototype.gridset_i = function(x,y,c) { if (x < 0 || y < 0 || x >= this.width || y >= this.height) return; this.code[y][x]=c; }; BefObject.prototype.gridget_i = function(x,y) { if (x < 0 || y < 0 || x >= this.width || y >= this.height) return 0; return this.code[y][x]; }; BefObject.prototype.updateUI = function() { switch (this.state) { case BefState.INITIAL: cssCtrlState(this.btnStart, 'ctrl_btn_disabled', true); cssCtrlState(this.btnSpeed, 'ctrl_btn_disabled', true); cssCtrlState(this.btnStop, 'ctrl_btn_disabled', false); cssCtrlState(this.btnReset, 'ctrl_btn_disabled', false); cssCtrlState(this.btnEdit, 'ctrl_btn_disabled', true); cssCtrlState(this.pnlBottom, 'generic_collapsed', false); cssCtrlState(this.pnlEditArea, 'generic_collapsed', false); cssCtrlState(this.pnlCode, 'generic_collapsed', true); break; case BefState.RUNNING: cssCtrlState(this.btnStart, 'ctrl_btn_disabled', false); cssCtrlState(this.btnSpeed, 'ctrl_btn_disabled', true); cssCtrlState(this.btnStop, 'ctrl_btn_disabled', true); cssCtrlState(this.btnReset, 'ctrl_btn_disabled', true); cssCtrlState(this.btnEdit, 'ctrl_btn_disabled', false); cssCtrlState(this.pnlBottom, 'generic_collapsed', true); cssCtrlState(this.pnlEditArea, 'generic_collapsed', false); cssCtrlState(this.pnlCode, 'generic_collapsed', true); break; case BefState.PAUSED: cssCtrlState(this.btnStart, 'ctrl_btn_disabled', true); cssCtrlState(this.btnSpeed, 'ctrl_btn_disabled', true); cssCtrlState(this.btnStop, 'ctrl_btn_disabled', false); cssCtrlState(this.btnReset, 'ctrl_btn_disabled', true); cssCtrlState(this.btnEdit, 'ctrl_btn_disabled', false); cssCtrlState(this.pnlBottom, 'generic_collapsed', true); cssCtrlState(this.pnlEditArea, 'generic_collapsed', false); cssCtrlState(this.pnlCode, 'generic_collapsed', true); break; case BefState.FINISHED: cssCtrlState(this.btnStart, 'ctrl_btn_disabled', false); cssCtrlState(this.btnSpeed, 'ctrl_btn_disabled', false); cssCtrlState(this.btnStop, 'ctrl_btn_disabled', false); cssCtrlState(this.btnReset, 'ctrl_btn_disabled', true); cssCtrlState(this.btnEdit, 'ctrl_btn_disabled', false); cssCtrlState(this.pnlBottom, 'generic_collapsed', true); cssCtrlState(this.pnlEditArea, 'generic_collapsed', false); cssCtrlState(this.pnlCode, 'generic_collapsed', true); break; case BefState.EDIT: cssCtrlState(this.btnStart, 'ctrl_btn_disabled', true); cssCtrlState(this.btnSpeed, 'ctrl_btn_disabled', false); cssCtrlState(this.btnStop, 'ctrl_btn_disabled', false); cssCtrlState(this.btnReset, 'ctrl_btn_disabled', true); cssCtrlState(this.btnEdit, 'ctrl_btn_disabled', false); cssCtrlState(this.pnlBottom, 'generic_collapsed', false); cssCtrlState(this.pnlEditArea, 'generic_collapsed', true); cssCtrlState(this.pnlCode, 'generic_collapsed', false); break; } this.btnSpeed.innerHTML = this.simspeed.str; }; BefObject.prototype.getDisplayHTML = function() { let str = ''; for (let y=0; y < this.height; y++) { for (let x=0; x < this.width; x++) { let cc = this.code[y][x]; let chr = String.fromCharCode(cc); if (chr === '&') chr = '&'; else if (chr === '<') chr = '<'; else if (chr === '>') chr = '>'; else if (cc === 32 ) chr = ' '; else if (cc<10 && cc>=0 ) chr = ''+cc+''; else if (cc<32 && cc>=10) chr = ''+String.fromCharCode(65+cc)+''; else if (cc>127 || cc<0 ) chr = 'X'; if (x === this.position[0] && y === this.position[1]) chr = '' + chr + ''; str += chr; } str += '
'; } return str; }; BefObject.prototype.getDisplayRaw = function() { let str = ''; for (let y=0; y < this.height; y++) { for (let x=0; x < this.width; x++) { str += String.fromCharCode(this.code[y][x]); } str += '\n'; } return str; }; BefObject.prototype.updateDisplay = function() { this.pnlCode.innerHTML = this.getDisplayHTML(); this.pnlOutput.innerHTML = htmlescape(this.output); this.pnlStack.innerHTML = this.stack.revjoin("
"); this.lblStackSize.innerHTML = "(" + this.stack.length + ")"; }; BefObject.prototype.parseBef = function(str) { const lines = str.replace('\r', '').split('\n'); let max = 0; for (let line of lines) max = Math.max(max, line.length); let result = []; for (let _line of lines) { let line = _line.replace('\r', '').replace('\n', ''); let row = []; for(let i=0; i < max; i++) { row.push((i < line.length ? (line[i].charCodeAt(0)) : 32)); } result.push(row) } return [result, max, result.length]; }; function cssCtrlState(e, cls, state) { if (e === undefined) return; if (state) { if (!e.classList.contains(cls)) return; e.classList.remove(cls); } else { if (e.classList.contains(cls)) return; e.classList.add(cls); } } function htmlescape(str) { str = str.replace(/&/g, "&"); str = str.replace(//g, ">"); str = str.replace(/ /g, " "); str = str.replace(/\n/g, "
"); return str; } window.onload = function () { let elements = document.getElementsByClassName("b93rnr_base"); for (let elem of elements) { let befungeObject = new BefObject(elem); if (befungeObject.btnStart !== undefined) befungeObject.btnStart.onclick = function () { if (befungeObject.btnStart.classList.contains('ctrl_btn_disabled')) return; befungeObject.start(); }; if (befungeObject.btnStop !== undefined) befungeObject.btnStop.onclick = function () { if (befungeObject.btnStop.classList.contains('ctrl_btn_disabled')) return; befungeObject.stop(); }; if (befungeObject.btnReset !== undefined) befungeObject.btnReset.onclick = function () { if (befungeObject.btnReset.classList.contains('ctrl_btn_disabled')) return; befungeObject.reset(); }; if (befungeObject.btnSpeed !== undefined) befungeObject.btnSpeed.onclick = function () { if (befungeObject.btnSpeed.classList.contains('ctrl_btn_disabled')) return; befungeObject.incSpeed(); }; if (befungeObject.btnEdit !== undefined) befungeObject.btnEdit.onclick = function () { if (befungeObject.btnEdit.classList.contains('ctrl_btn_disabled')) return; befungeObject.startEdit(); }; } };