diff --git a/index.html b/index.html index b44715e..587e8c3 100644 --- a/index.html +++ b/index.html @@ -467,12 +467,11 @@

Rules

Select an interesting premade setting (using custom activations).

diff --git a/js/automata.js b/js/automata.js index 917431e..42b0284 100644 --- a/js/automata.js +++ b/js/automata.js @@ -455,7 +455,7 @@ export class LangtonsAnt extends Automata { newAnts[i][0] = (newAnts[i][0] + 1) % this.cols; // East break; case 2: - newAnts[i][1] = (newAnts[i][1] + 1) % this.cols; // South + newAnts[i][1] = (newAnts[i][1] + 1) % this.rows; // South break; case 3: newAnts[i][0] = (newAnts[i][0] - 1 + this.cols) % this.cols; // West @@ -900,6 +900,8 @@ export class WireWorld extends Automata { // Fill only conductors when penstate is electrons if (this.penState == 2 || this.penState == 3) { if (this.grid[y][x] != 0) this.grid[y][x] = this.penState; + } else if (this.penState == 4) { + if (this.grid[y][x] == 2 || this.grid[y][x] == 3) this.grid[y][x] = 1; } else this.grid[y][x] = this.penState; } } @@ -914,12 +916,11 @@ export class WireWorld extends Automata { 1: "Conductor", 2: "Electron Head", 3: "Electron Tail", + 4: "Signal Eraser", }; // Change pen state - this.penState = (this.penState + 1) % 4; - setConsoleText( - `Updated pen to draw ${stateNames[this.penState]} [${this.penState}]` - ); + this.penState = (this.penState + 1) % 5; + setConsoleText(`Updated pen to draw ${stateNames[this.penState]}`); window.requestAnimationFrame(() => this.drawCursor()); } @@ -930,6 +931,7 @@ export class WireWorld extends Automata { 1: "rgba(255, 255, 0, 0.8)", 2: "rgba(0, 0, 255, 0.8)", 3: "rgba(255, 0, 0, 0.8)", + 4: "rgba(0, 255, 0, 0.8)", }; return stateColors[this.penState]; } @@ -957,6 +959,7 @@ export class RPSGame extends Automata { this.winCondition = winCondition; // Number of states played with, ranges between 3 and 5 this.stateCount = [3, 4, 5].includes(stateCount) ? 3 : stateCount; + console.log(stateCount, this.stateCount); // Implement GPU kernel to update grid this.gridUpdateKernel = this.gpu diff --git a/js/inputs/settings.js b/js/inputs/settings.js index 54125e0..dcbcf08 100644 --- a/js/inputs/settings.js +++ b/js/inputs/settings.js @@ -334,6 +334,7 @@ document.getElementById("rps-state-select").onchange = (event) => { }; //! Neural CA Rules +// Randomize grid weights document.getElementById("neural-randomize").onclick = (_) => { const settingsContainer = document.getElementById("neural-settings"); const rows = parseInt(settingsContainer.querySelector(".row-select").value); @@ -343,7 +344,7 @@ document.getElementById("neural-randomize").onclick = (_) => { function randomWeight() { let randWeight = (Math.random() * 2 - 1).toFixed(4); - if (randWeight < 0 && Math.random() < 0.1) + if (randWeight < 0 && Math.random() < 0.15) randWeight = Math.abs(randWeight); // Force more positive weights return randWeight; } @@ -378,9 +379,8 @@ presetSelector.onchange = (event) => { [-0.9, -0.66, -0.9], [0.68, -0.9, 0.68], ], - activation: eval( - `(${"function activation(x) {\n\treturn -(1 / Math.pow(2, 0.6 * Math.pow(x, 2))) + 1\n}"})` - ), + activation: + "function activation(x) {\n\treturn -(1 / Math.pow(2, 0.6 * Math.pow(x, 2))) + 1\n}", }, stars: { weights: [ @@ -388,19 +388,7 @@ presetSelector.onchange = (event) => { [-0.759, 0.627, -0.759], [0.565, -0.716, 0.565], ], - activation: eval( - `(${"function activation(x) {\n\treturn Math.abs(x)\n}"})` - ), - }, - "slime-mold": { - weights: [ - [0.8, -0.85, 0.8], - [-0.85, -0.2, -0.85], - [0.8, -0.85, 0.8], - ], - activation: eval( - `(${"function activation(x) {\n\treturn -1 / (0.89 * Math.pow(x, 2) + 1) + 1\n}"})` - ), + activation: "function activation(x) {\n\treturn Math.abs(x)\n}", }, waves: { weights: [ @@ -408,9 +396,7 @@ presetSelector.onchange = (event) => { [-0.716, 0.627, -0.716], [0.565, -0.716, 0.565], ], - activation: eval( - `(${"function activation(x) {\n\treturn Math.abs(1.2 * x)\n}"})` - ), + activation: "function activation(x) {\n\treturn Math.abs(1.2 * x)\n}", }, mitosis: { weights: [ @@ -418,9 +404,8 @@ presetSelector.onchange = (event) => { [0.88, 0.4, 0.88], [-0.939, 0.88, -0.939], ], - activation: eval( - `(${"function activation(x) {\n\treturn -1 / (0.91 * Math.pow(x, 2) + 1) + 1\n}"})` - ), + activation: + "function activation(x) {\n\treturn -1 / (0.91 * Math.pow(x, 2) + 1) + 1\n}", }, pathways: { weights: [ @@ -428,9 +413,8 @@ presetSelector.onchange = (event) => { [1.0, 1.0, 1.0], [0.0, 1.0, 0.0], ], - activation: eval( - `(${"function activation(x) {\n\treturn 1 / Math.pow(2, Math.pow(x - 3.5, 2))\n}"})` - ), + activation: + "function activation(x) {\n\treturn 1 / Math.pow(2, Math.pow(x - 3.5, 2))\n}", }, "game-of-life": { weights: [ @@ -438,9 +422,8 @@ presetSelector.onchange = (event) => { [1.0, 9.0, 1.0], [1.0, 1.0, 1.0], ], - activation: eval( - `(${"function activation(x) {\n\tif (x == 3 || x == 11 || x == 12) {\n\treturn 1;\n}\nreturn 0}"})` - ), + activation: + "function activation(x) {\n\tx = Math.round(x);\n\tif (x == 3 || x == 11 || x == 12) return 1;\n\treturn 0;\n}", }, }; @@ -453,11 +436,9 @@ presetSelector.onchange = (event) => { createGrid("neural-settings"); // Update activation - console.log(event.target.value); - activationSelector.selectedIndex = activationSelector.options.length - 1; // Set to custom activation - automata.activation = argMap[event.target.value].activation; - editor.setValue(automata.activation.toString()); + editor.setValue(argMap[event.target.value].activation); automata.randomize(); + automata.resetAnimationRequests(); }; // Handle changes in activation @@ -485,9 +466,11 @@ function setActivation(type) { }) ); automata.activation = evaluatedFuncMap[type]; + automata.resetAnimationRequests(); // Update code editor editor.setValue(automata.activation.toString()); + activationSelector.selectedIndex = Object.keys(funcMap).indexOf(type); } // Intialize activation func code editor @@ -511,11 +494,14 @@ editor.session.on("change", function (_) { const code = editor.getValue(); try { // Evaluate the code and test it on a value - const activation = genShieldedFunction(eval(`(${code})`)); - const testValues = [Math.random(), Math.random(), Math.random(), 0, 1]; - testValues.forEach((value) => activation(value)); - automata.activation = activation; - setConsoleText("Updated Activation Function!"); + if (code) { + const activation = genShieldedFunction(eval(`(${code})`)); + const testValues = [Math.random(), Math.random(), Math.random(), 0, 1]; + testValues.forEach((value) => activation(value)); + automata.activation = activation; + automata.resetAnimationRequests(); + setConsoleText("Updated Activation Function!"); + } } catch (error) { console.log(`Error: ${error}`); setConsoleText("Invalid Activation Function!"); diff --git a/js/inputs/userInput.js b/js/inputs/userInput.js index a5f9aad..2af6c8f 100644 --- a/js/inputs/userInput.js +++ b/js/inputs/userInput.js @@ -228,6 +228,9 @@ function handleAction(action) { automata.baseState ? automata.baseState : 0 ) ); + if (automata.ants) { + automata.ants = []; + } automata.resetAnimationRequests(); setConsoleText("Cleared Grid"); break;