Attempting to build these circuits is highly unadvisable.
Log in to post a comment.
const branchingChance = 1.0; // min=0.01, max=1.0, step=0.01
const branchingMultiplier = 1; // min=0, max=1, step=0.01
const branchingDeathChance = 0.6; // min=0.01, max=1.0, step=0.01
const multiLeadComponentChance = 1.0; // min=0.01, max=1.0, step=0.01
const twoLeadComponentChance = 1.0; // min=0.01, max=1.0, step=0.01
const lineChance = 0.2; // min=0.01, max=1.0, step=0.01
const turnChance = 0.2; // min=0.01, max=1.0, step=0.01
const energyLossMultiplier = 0.5; // min=0.01, max=1.0, step=0.01
Turtle.prototype.drawResistor = function() {
const angle = 60;
const connector = 4*scale;
this.pendown();
this.forward(connector);
this.left(angle);
this.forward(1*scale);
this.right(2*angle);
this.forward(2*scale);
this.left(2*angle);
this.forward(2*scale);
this.right(2*angle);
this.forward(2*scale);
this.left(2*angle);
this.forward(2*scale);
this.right(2*angle);
this.forward(2*scale);
this.left(2*angle);
this.forward(1*scale);
this.right(angle);
this.forward(connector);
this.penup();
this.energy *= 0.95;
}
Turtle.prototype.drawInductor = function() {
const connector = 4*scale;
const radius = 1.5*scale;
this.pendown();
this.forward(connector);
this.penup();
for (let i = 0; i < 3; i++) {
this.left(90);
this.pendown();
this.circle(radius, 180, 40);
this.penup();
this.left(90);
}
this.pendown();
this.forward(connector);
this.penup();
this.energy *= 0.9;
}
Turtle.prototype.drawDiode = function() {
const connector = 4*scale;
const base = 1.5*scale;
const length = 2.5*scale;
const side = Math.sqrt(base*base+length*length);
const a = Math.atan(length/base)*180/Math.PI;
this.pendown();
this.forward(connector);
this.left(90);
this.forward(base);
this.right(180-a);
this.forward(side);
this.left(90-a);
this.right((a-270)%360);
this.forward(side);
this.right(180-a);
this.forward(base);
this.penup();
this.right(90);
this.forward(length);
this.left(90);
this.backward(base);
this.pendown();
this.forward(2*base);
this.penup();
this.backward(base);
this.right(90);
this.pendown();
this.forward(connector);
this.energy *= 0.97;
this.penup();
}
Turtle.prototype.drawReverseDiode = function () {
this.penup();
this.forward(10.5*scale);
const helper = this.clone();
helper.seth((this.h()-180)%360);
helper.drawDiode();
}
Turtle.prototype.drawZenerDiode = function() {
const connector = 4*scale;
const base = 1.5*scale;
const length = 2.5*scale;
const side = Math.sqrt(base*base+length*length);
const a = Math.atan(length/base)*180/Math.PI;
this.pendown();
this.forward(connector);
this.left(90);
this.forward(base);
this.right(180-a);
this.forward(side);
this.left(90-a);
this.right((a-270)%360);
this.forward(side);
this.right(180-a);
this.forward(base);
this.penup();
this.right(90);
this.forward(length);
this.left(90);
this.backward(base);
this.left(60);
this.backward(base/2);
this.pendown();
this.forward(base/2);
this.right(60);
this.forward(2*base);
this.left(60);
this.forward(base/2);
this.penup();
this.backward(base/2);
this.right(60);
this.backward(base);
this.right(90);
this.pendown();
this.forward(connector);
this.energy *= 0.97;
this.penup();
}
Turtle.prototype.drawRectifier = function() {
const connector = 4*scale;
let newTurtles = [];
this.pendown();
this.forward(connector);
const helper = this.clone();
this.left(45);
this.drawDiode();
const a = this.clone();
a.left(45);
a.forward(connector);
a.drawLine();
newTurtles.push(a);
this.right(90);
this.drawDiode();
this.left(45);
this.pendown();
this.forward(connector);
this.penup();
helper.right(45);
helper.drawDiode();
const b = helper.clone();
b.right(45);
b.forward(connector);
b.drawLine();
newTurtles.push(b);
helper.left(90);
helper.drawDiode();
this.energy *= 0.1;
newTurtles = newTurtles.map(t => {
t.energy = this.energy / 2;
return t;
})
return newTurtles;
}
Turtle.prototype.drawTransistor = function() {
const connector = 8*scale;
const radius = 4*scale;
this.energy *= 0.5;
this.pendown();
this.forward(connector);
this.right(75);
this.forward(radius/1.5);
this.left(75);
this.penup();
this.backward(1.5*scale);
this.pendown();
this.forward(1.5*scale+radius/4);
const helper = this.clone();
this.forward(1.5*scale+radius/4);
this.penup();
this.backward(1.5*scale);
this.left(75);
this.pendown();
this.forward(radius/1.5);
this.right(75);
this.forward(connector);
this.penup();
helper.right(90);
helper.forward(radius/2);
helper.right(90);
helper.circle(radius);
helper.left(90);
helper.forward(connector);
return [helper.spawn(1)];
}
Turtle.prototype.drawOpAmp = function() {
const connector = 6*scale;
const base = 3*scale;
const length = 5*scale;
const side = Math.sqrt(base*base+length*length);
const a = Math.atan(length/base)*180/Math.PI;
const h = Math.round(this.h())%360;
this.energy *= 0.8;
this.pendown();
if (this.h() === 180) {
this.left(45);
this.forward(connector);
this.left(45);
this.forward(connector);
this.left(45);
}
this.edgeRotate(0);
this.seth(0);
this.forward(connector);
this.left(90);
this.penup();
this.forward(base/2);
this.right(180-a);
this.pendown();
this.forward(side);
this.left(90-a);
const newTurtle = this.clone();
newTurtle.forward(connector);
this.right((a-270)%360);
this.forward(side);
this.right(180-a);
this.forward(2*base);
this.penup();
this.backward(3*base/2);
this.pendown();
this.left(90);
this.forward(connector);
this.penup();
return [newTurtle];
}
Turtle.prototype.drawCapacitor = function() {
const connector = 4*scale;
const base = 3*scale;
const gap = 1*scale;
this.pendown();
this.forward(connector);
this.left(90);
this.penup();
this.backward(base/2);
this.pendown();
this.forward(base);
this.penup();
this.right(90);
this.forward(gap);
this.left(90);
this.pendown();
this.backward(base);
this.penup();
this.forward(base/2);
this.right(90);
this.pendown();
this.forward(connector);
this.penup();
this.energy *= 0.9;
}
Turtle.prototype.drawGround = function() {
const connector = 4*scale;
const base = 3*scale;
const gap = 1*scale;
this.pendown();
this.forward(connector);
this.edgeRotate(90);
this.seth(90);
this.forward(base);
this.penup();
this.left(90);
this.backward(base/2);
const x = this.x();
for (let i = 0; i < 3; i++) {
this.forward(i*base/5);
this.pendown();
this.forward(base-i*2*base/5);
this.penup();
this.setx(x);
this.sety(this.y()+gap);
}
this.energy = 0;
}
Turtle.prototype.drawSignalGround = function() {
const connector = 4*scale;
const base = 1.5*scale;
const gap = 1*scale;
const length = 2.5*scale;
const side = Math.sqrt(base*base+length*length);
const a = Math.atan(length/base)*180/Math.PI;
this.pendown();
this.forward(connector);
this.edgeRotate(90);
this.seth(90);
this.forward(connector);
this.left(90);
this.forward(base);
this.right(180-a);
this.forward(side);
this.left(90-a);
this.right((a-270)%360);
this.forward(side);
this.right(180-a);
this.forward(base);
this.right(90);
this.penup();
this.forward(length);
this.energy = 0;
}
Turtle.prototype.drawVcc = function() {
const connector = 4*scale;
const base = 1.5*scale;
const gap = 1*scale;
const length = 2.5*scale;
const side = Math.sqrt(base*base+length*length);
const a = Math.atan(length/base)*180/Math.PI;
this.pendown();
this.forward(connector);
this.edgeRotate(270);
this.seth(270);
this.forward(connector);
this.penup();
this.left(90);
this.forward(base);
this.pendown();
this.right(180-a);
this.forward(side);
this.left(90-a);
this.right((a-270)%360);
this.forward(side);
this.right(180-a);
this.penup();
this.forward(base);
this.right(90);
this.pendown();
this.forward(length);
this.penup();
this.energy = 0;
}
Turtle.prototype.drawInput = function() {
const connector = 2*scale;
const base = scale;
this.pendown();
this.forward(connector);
this.edgeRotate(180);
this.seth(180);
this.forward(connector);
this.penup();
this.left(90);
this.forward(base/2);
this.right(90);
this.pendown();
this.forward(base);
this.circle(base);
this.penup();
this.energy = 0;
}
Turtle.prototype.drawOutput = function() {
const connector = 2*scale;
const length = 2*scale;
const base = scale;
const side = Math.sqrt(base*base+length*length);
const a = Math.atan(length/base)*180/Math.PI;
this.pendown();
this.forward(connector);
this.edgeRotate(0);
this.seth(0);
this.forward(connector);
this.penup();
this.left(90);
this.forward(base);
this.pendown();
this.right(180-a);
this.forward(side);
this.left(90-a);
this.right((a-270)%360);
this.forward(side);
this.right(180-a);
this.penup();
this.forward(base);
this.right(90);
this.pendown();
this.forward(length);
this.penup();
this.energy = 0;
}
Turtle.prototype.drawLine = function() {
const lut = [4, 7, 9];
const len = lut[Math.floor(Math.random()*lut.length)]*scale;
this.penup();
this.forward(len);
if (Math.abs(this.y()) > 80 || Math.abs(this.x()) > 70) {
this.backward(len);
this.end();
} else {
this.backward(len);
this.pendown();
this.forward(len);
this.penup();
this.energy *= 0.99;
}
}
Turtle.prototype.drawConnector = function() {
const size = 6;
const x = this.x();
const y = this.y();
for (let n = 1; n < size; n++) {
this.left(90);
this.forward(n/size);
this.right(90);
this.pendown();
this.circle(n/size);
this.penup();
this.left(90);
this.backward(n/size);
this.right(90);
}
this.goto(x,y);
this.penup();
}
Turtle.prototype.edgeRotate = function(dir) {
const connector = 4*scale;
const h = Math.round(this.h())%360;
const left = this.x() > 0 ? this.left : this.right;
const right = this.x() > 0 ? this.right : this.left;
let angle = (h-(dir+360))%360;
for (let i = 0; angle > 0; i++, angle-=45) {
if (dir > 270 || dir < 90) {
left.call(this, 45);
} else {
right.call(this, 45);
}
this.forward(i%2==1 ? 2*connector : connector);
}
}
Turtle.prototype.spawn = function(n) {
const newTurtle = this.clone();
newTurtle.right(n%2==0 ? 90 : 270);
newTurtle.drawLine();
newTurtle.energy = this.energy / (1+Math.random());
return newTurtle;
}
Turtle.prototype.end = function() {
const h = Math.round(this.h())%360;
if (h === 270) {
this.topEnders[Math.floor(Math.random()*this.topEnders.length)].call(this);
}
else if (h === 0) {
this.rightEnders[Math.floor(Math.random()*this.rightEnders.length)].call(this);
}
else if (h === 90) {
this.bottomEnders[Math.floor(Math.random()*this.bottomEnders.length)].call(this);
}
else if (h === 180) {
this.leftEnders[Math.floor(Math.random()*this.leftEnders.length)].call(this);
}
else if (this.y() > 0) {
if (this.y() < 60 && this.x() > 60) {
this.rightEnders[Math.floor(Math.random()*this.rightEnders.length)].call(this);
} else {
this.bottomEnders[Math.floor(Math.random()*this.bottomEnders.length)].call(this);
}
} else {
if (this.y() > -60 && this.x() < -60) {
this.leftEnders[Math.floor(Math.random()*this.leftEnders.length)].call(this);
} else {
this.topEnders[Math.floor(Math.random()*this.topEnders.length)].call(this);
}
}
}
Turtle.prototype.fns = [
Turtle.prototype.drawResistor,
Turtle.prototype.drawInductor,
Turtle.prototype.drawDiode,
Turtle.prototype.drawReverseDiode,
Turtle.prototype.drawZenerDiode,
Turtle.prototype.drawCapacitor,
];
Turtle.prototype.spawners = [
Turtle.prototype.drawRectifier,
Turtle.prototype.drawTransistor,
Turtle.prototype.drawOpAmp,
];
Turtle.prototype.leftEnders = [
Turtle.prototype.drawInput,
];
Turtle.prototype.rightEnders = [
Turtle.prototype.drawOutput,
];
Turtle.prototype.topEnders = [
Turtle.prototype.drawVcc,
];
Turtle.prototype.bottomEnders = [
Turtle.prototype.drawGround,
Turtle.prototype.drawSignalGround,
]
let scale = 1;
const initialEnergy = 1000;
const maxNodes = 1000;
Canvas.setpenopacity(1);
const topTurtle = new Turtle();
topTurtle.energy = initialEnergy;
topTurtle.penup();
topTurtle.goto(0,0);
topTurtle.seth(Math.random() > 0.5 ? 270 : 180);
const bottomTurtle = topTurtle.clone();
bottomTurtle.seth((bottomTurtle.h()+180)%360)
let turtles = [topTurtle,bottomTurtle];
let livingTurtles = [];
let newTurtles = [];
let skipped = false;
let nodes = 0;
function walk(i) {
newTurtles = livingTurtles = [];
turtles.map((turtle, idx) => {
if (turtle.energy < 1 && turtle.energy > 0) {
if (turtle.y() > 0) {
turtle.drawGround();
} else {
turtle.drawVcc();
}
}
if (turtle.energy < 1 || turtle.x() > 100 || turtle.y() > 100 || turtle.x() < -100 || turtle.y() < -100) {
turtles[idx] = null;
} else {
skipped = false;
// Branching
if (Math.random()*branchingChance > 0.99525) {
turtle.drawConnector();
for (let h = branchingMultiplier+Math.round(Math.random()); h > 0; h--) {
newTurtles.push(turtle.spawn(h));
}
// Sometimes, kill the original turtle, so a T-connection is created.
if (newTurtles.length === 2 && Math.random() >= branchingDeathChance) {
turtles[idx] = null;
}
}
// Components with more than 2 leads
else if (i > 5 && Math.random()*multiLeadComponentChance > 0.9925) {
const possiblyTurtles = turtle.spawners[Math.floor(Math.random()*turtle.spawners.length)].call(turtle);
if (!!possiblyTurtles && possiblyTurtles.length) {
newTurtles = newTurtles.concat(possiblyTurtles);
}
nodes++;
}
// Components
else if (i > 1 && Math.random()*twoLeadComponentChance > 0.95) {
const possiblyTurtles = turtle.fns[Math.floor(Math.random()*turtle.fns.length)].call(turtle);
if (!!possiblyTurtles && possiblyTurtles.length) {
newTurtles = newTurtles.concat(possiblyTurtles);
}
nodes++;
}
// Voltages and grounds
else if (i > 15 && (Math.abs(turtle.y()) > 70 || Math.abs(turtle.x()) > 70)) {
turtle.end();
nodes++;
}
// Lines
else if (Math.random() <= lineChance) {
turtle.drawLine();
}
else {
skipped = true;
}
// Turning
if (!skipped && Math.random() < turnChance) {
Math.random() > 0.5
? turtle.left((i%5!==0 && Math.random() < 0.9) ? 45 : 90)
: turtle.right((i%7!==0 && Math.random() < 0.9) ? 45 : 90);
}
turtle.energy *= energyLossMultiplier;
}
})
livingTurtles = turtles.filter(t => t != null);
turtles = livingTurtles.concat(newTurtles);
return nodes < maxNodes && turtles.length != 0;
}