Skip to content

Commit

Permalink
Langton's Ant bugfix
Browse files Browse the repository at this point in the history
  • Loading branch information
Niyaz-Mohamed committed Aug 30, 2024
1 parent 8ebc7d9 commit d0263c2
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 45 deletions.
3 changes: 1 addition & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -467,12 +467,11 @@ <h2>Rules</h2>
<p class="desc">Select an interesting premade setting (using custom activations).</p>
<select id="neural-preset-select">
<option value="worms" selected>Worms</option>
<option value="game-of-life">Game of Life</option>
<option value="stars">Stars</option>
<option value="slime-mold">Slime Mold</option>
<option value="waves">Waves</option>
<option value="mitosis">Mitosis</option>
<option value="pathways">Pathways</option>
<option value="game-of-life">Game of Life</option>
</select>
</div>
<div class="rule-div">
Expand Down
13 changes: 8 additions & 5 deletions js/automata.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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());
}

Expand All @@ -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];
}
Expand Down Expand Up @@ -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
Expand Down
62 changes: 24 additions & 38 deletions js/inputs/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -378,69 +379,51 @@ 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: [
[0.565, -0.716, 0.565],
[-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: [
[0.565, -0.716, 0.565],
[-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: [
[-0.939, 0.88, -0.939],
[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: [
[0.0, 1.0, 0.0],
[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: [
[1.0, 1.0, 1.0],
[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}",
},
};

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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!");
Expand Down
3 changes: 3 additions & 0 deletions js/inputs/userInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ function handleAction(action) {
automata.baseState ? automata.baseState : 0
)
);
if (automata.ants) {
automata.ants = [];
}
automata.resetAnimationRequests();
setConsoleText("Cleared Grid");
break;
Expand Down

0 comments on commit d0263c2

Please sign in to comment.