-
Notifications
You must be signed in to change notification settings - Fork 17
/
ga.js
76 lines (66 loc) · 1.71 KB
/
ga.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
// Start the game over
function resetGame() {
counter = 0;
// Resetting best bird score to 0
if (bestBird) {
bestBird.score = 0;
}
pipes = [];
}
// Create the next generation
function nextGeneration() {
resetGame();
// Normalize the fitness values 0-1
normalizeFitness(allBirds);
// Generate a new set of birds
activeBirds = generate(allBirds);
// Copy those birds to another array
allBirds = activeBirds.slice();
}
// Generate a new population of birds
function generate(oldBirds) {
let newBirds = [];
for (let i = 0; i < oldBirds.length; i++) {
// Select a bird based on fitness
let bird = poolSelection(oldBirds);
newBirds[i] = bird;
}
return newBirds;
}
// Normalize the fitness of all birds
function normalizeFitness(birds) {
// Make score exponentially better?
for (let i = 0; i < birds.length; i++) {
birds[i].score = pow(birds[i].score, 2);
}
// Add up all the scores
let sum = 0;
for (let i = 0; i < birds.length; i++) {
sum += birds[i].score;
}
// Divide by the sum
for (let i = 0; i < birds.length; i++) {
birds[i].fitness = birds[i].score / sum;
}
}
// An algorithm for picking one bird from an array
// based on fitness
function poolSelection(birds) {
// Start at 0
let index = 0;
// Pick a random number between 0 and 1
let r = random(1);
// Keep subtracting probabilities until you get less than zero
// Higher probabilities will be more likely to be fixed since they will
// subtract a larger number towards zero
while (r > 0) {
r -= birds[index].fitness;
// And move on to the next
index += 1;
}
// Go back one
index -= 1;
// Make sure it's a copy!
// (this includes mutation)
return birds[index].copy();
}