-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdot.js
More file actions
173 lines (156 loc) · 4.58 KB
/
dot.js
File metadata and controls
173 lines (156 loc) · 4.58 KB
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/**
* Single one of the player dots
*/
class Bx_Player {
/**
* The pixel size of the player. A constant.
*
* @todo Change to the game option.
*/
static get PLAYER_SIZE() {
return 10;
}
/**
* Creates a new fearsome warrior dot
*
* @param {Bx_Game} game The game itself (because of the data)
* @param {Bx_PlayerBrain} brain The brain (if not provided from the parent, don't be sad, you will get the brand new random one)
* @param {bool} best TRUE if this is the best player from the previous generation (therefore kept unmutated)
* @returns {Bx_Player}
*/
constructor(game, brain = false, best = false) {
this.game = game;
this.x = this.game.data.start.x;
this.y = this.game.data.start.y;
if (brain === false) {
this.brain = new Bx_playerBrain(this.game.data.brain_size);
} else {
this.brain = brain;
}
this.fitness = 0;
this.dead = false;
this.finished = false;
this.best = best;
}
/**
* Checks the collisions of the player with a wall, obstacle or (luckily) with the goal
*
* @param {int} steps The number of steps taken to become victorious... or dead
*/
collisionCheck(steps) {
if (
this.x < 0 + this.constructor.PLAYER_SIZE / 2 ||
this.x > 500 - this.constructor.PLAYER_SIZE / 2 ||
this.y < 0 + this.constructor.PLAYER_SIZE / 2 ||
this.y > 500 - this.constructor.PLAYER_SIZE / 2
) {
if (this.dead === false) {
this.dead = steps;
}
}
for (var i = 0; i < this.game.data.obstacles.length; i++) {
var obstacle = this.game.data.obstacles[i];
if (
this.x <
Math.max(obstacle.x1, obstacle.x2) +
this.constructor.PLAYER_SIZE / 2 &&
this.x >
Math.min(obstacle.x1, obstacle.x2) -
this.constructor.PLAYER_SIZE / 2 &&
this.y <
Math.max(obstacle.y1, obstacle.y2) +
this.constructor.PLAYER_SIZE / 2 &&
this.y >
Math.min(obstacle.y1, obstacle.y2) - this.constructor.PLAYER_SIZE / 2
) {
if (this.dead === false) {
this.dead = steps;
}
}
}
if (
Math.sqrt(
Math.pow(this.x - this.game.data.goal.x, 2) +
Math.pow(this.y - this.game.data.goal.y, 2)
) <=
this.constructor.PLAYER_SIZE / 2
) {
if (this.finished === false) {
this.finished = steps;
}
}
}
/**
* Moves the player to a brand new location (specified by brain)
*
* @param {int} i The step number (it's like stepbrother except it's a number)
*/
step(i) {
this.collisionCheck(i);
if (this.dead === false && this.finished === false) {
this.x += Math.cos(this.brain.moves[i]) * this.game.data.step_size;
this.y += Math.sin(this.brain.moves[i]) * this.game.data.step_size;
}
}
/**
* Renders the player position.
*
* @param {int} step The number of steps taken
*/
render(step) {
let bestStep = this.finished - this.game.data.step_size;
Bx_Render.renderPlayer(this, step);
if (this.best && this.finished) {
bestPath.innerText = 'Best path to goal: ' + +bestStep + ' Steps';
gen = game.population.generation % 10;
var gen = document.getElementById('genCounter').innerText;
var bestPath2 = 'best_path' + gen;
document.getElementById(bestPath2).innerHTML = bestStep;
} else if (this.best) {
var gen = document.getElementById('genCounter').innerText;
var bestPath2 = 'best_path' + gen;
document.getElementById(bestPath2).innerHTML = 'n/a';
}
}
/**
* To see how good is the player
*
* @returns {Number}
*/
calculateFitness() {
if (this.finished) {
this.fitness =
1.0 / 16.0 +
10000.0 / Math.pow(this.game.data.step_size - this.finished, 2);
} else {
this.fitness =
1.0 /
Math.pow(
Math.sqrt(
Math.pow(this.x - this.game.data.goal.x, 2) +
Math.pow(this.y - this.game.data.goal.y, 2)
),
2
);
}
if (this.dead) {
this.fitness *= this.dead / 1000.0;
}
return this.fitness;
}
/**
* Creates the offspring... and mutates it
*
* @param {bool} best TRUE if the best player of the previous generation is being cloned
* @returns {Bx_Player}
*/
clone(best = false) {
var brain = new Bx_playerBrain(0);
brain.moves = JSON.parse(JSON.stringify(this.brain.moves));
// If the player is not copy of the best parent, mutate it a bit
if (!best) {
brain.mutate();
}
return new Bx_Player(this.game, brain, best);
}
}