-
Notifications
You must be signed in to change notification settings - Fork 5
/
sketch.js
executable file
·122 lines (100 loc) · 2.59 KB
/
sketch.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
let outerWalls = []
let innerWalls = []
let walls = []
let center
let cars = []
let gen = 0
let autoNewGenCheck
let speedSlider
let startPos
let startHeading
function setup() {
createCanvas(800, 600)
let button = createButton('start new generation')
button.mousePressed(newGeneration)
center = createVector(width / 2, height / 2)
changeCircuit(2)
startHeading = -PI / 2
tf.setBackend('cpu')
}
const POPULATION_SIZE = 100
function newGeneration() {
if (cars.length === 0) {
cars = []
for (let i = 0; i < POPULATION_SIZE; i++) {
let car = new Car(startPos)
car.heading = startHeading
cars.push(car)
}
} else if (cars.length === 1) {
let car = cars[0]
for (let i = 1; i < POPULATION_SIZE; i++) {
let brain = car.brain.copy()
brain.mutate()
let newCar = new Car(startPos, brain)
newCar.heading = startHeading
cars.push(newCar)
}
}
else {
let newGen = []
let topNumber = Math.floor(cars.length * 0.1)
const bestCars = cars.sort((a, b) => b.currentScore - a.currentScore).slice(0, topNumber)
const totalFitness = bestCars.reduce((acc, car) => acc + car.currentScore, 0)
function roulettePick(parents, pick) {
let current = 0
for (const parent of parents) {
current += parent.currentScore
if (current > pick) {
return parent
}
}
}
const nbToKeep = 2
// keep the 2 best cars
for (let i = 0; i < nbToKeep; i++) {
let car = bestCars[i]
let brain = car.brain.copy()
let newCar = new Car(startPos, brain)
newCar.heading = startHeading
newGen.push(newCar)
}
while (newGen.length < POPULATION_SIZE) {
//Pick a pair
let pickA = random(0, totalFitness)
let pickB = random(0, totalFitness)
let parentA = roulettePick(bestCars, pickA)
let parentB = roulettePick(bestCars, pickB)
newGen.push(parentA.giveBirth(parentB))
}
for (let c of cars)
c.dispose()
cars = newGen
}
}
function draw() {
background(0)
stroke(255)
fill(255)
strokeWeight(1)
for (let w of walls) {
line(w.start.x, w.start.y, w.end.x, w.end.y)
}
stroke(0, 255, 0)
for (let car of cars) {
car.update()
car.draw()
}
}
function cross2d(v1, v2) {
return v1.x * v2.y - v1.y * v2.x
}
function changeCircuit(circuitIndex) {
const c = circuits[circuitIndex]
walls = []
for (let w of c.walls) {
walls.push(new Wall(w.start.x, w.start.y, w.end.x, w.end.y))
}
walls.push(new Wall(0, height / 2, width / 2, height / 2))
startPos = createVector(c.startPos.x, c.startPos.y)
}